Попытка напечатать общее пространство в байтах в каталоге и всех подкаталогах - PullRequest
3 голосов
/ 11 марта 2019

В настоящее время я пытаюсь создать программу переменного тока, которая подсчитывает общий размер файла в байтах данного каталога, включая сам каталог, все файлы в нем и все файлы и каталоги во всех подкаталогах.По сути, меня просят запрограммировать замену du -b в качестве команды.

Я думал, что у меня есть рабочее решение, но после первого каталога эта программа считает, что все записи, находящиеся глубже, являются каталогами, дажекогда они просто обычные файлы.Это включает в себя, когда я даю ему каталог, который на один градус глубже напрямую, скажем, давая ему ввод ./Directory1 вместо просто ..

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <dirent.h>

int du_function(char direc[]) {
    int total = 0;
    char str[100];
    strcpy(str, direc);
    struct stat sfile;
    struct dirent *de;
    DIR *dr = opendir(direc);
    if (dr == NULL) {
        printf("Could not open directory\n");
        return 0;
    }
    while ((de = readdir(dr)) != NULL) {
        printf("%s\n", de->d_name);
        stat(de->d_name, &sfile);
        if (S_ISDIR(sfile.st_mode) && strcmp(de->d_name, ".") != 0 &&
            strcmp(de->d_name, "..") != 0) {
            strcat(str, "/");
            strcat(str, de->d_name);
            printf("This is a directory called %s\n", str);
            total = total + du_function(str);
            strcpy(str, direc);
        }
        if (S_ISREG(sfile.st_mode) || strcmp(de->d_name, ".") == 0) {
            printf("Size in bytes = %ld\n", sfile.st_size);
            total = total + sfile.st_size;
            printf("The total is %d bytes so far.\n", total);
        }
    }
    printf("The total is %d bytes.\n", total);
    closedir(dr);
    return total;
}

int main(int argc, char *argv[]) {
    if (argc < 2) {
        char cwd[1] = ".";
        du_function(cwd);
    } else
        du_function(argv[1]);
    return 0;
}

Я нахожусь здесь в конце своего ума и попробовалмножество решений, но по какой-то причине S_ISDIR должен идентифицировать вещи как каталоги, которые не являются (или, скорее всего, получают неправильные данные от меня).

Ответы [ 2 ]

0 голосов
/ 11 марта 2019

Так же, как вы создаете путь для рекурсивного вызова, вы должны создать имя файла с ведущим каталогом для системного вызова stat. Ваша программа работает только для файлов в текущем каталоге.

Эффективный способ исправить вашу программу - передать достаточно большой буфер рекурсивной функции и постепенно построить путь и имена файлов:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <dirent.h>

long int du_function(char path[], size_t size) {
    size_t len = strlen(path);
    long int total = 0;
    struct stat sfile;
    struct dirent *de;
    DIR *dr = opendir(path);
    if (dr == NULL) {
        printf("Could not open directory %s\n", path);
        return 0;
    }
    while ((de = readdir(dr)) != NULL) {
        if (strcmp(de->d_name, "..") == 0)
            continue;
        //printf("%s\n", de->d_name);
        if (snprintf(path + len, size - len, "/%s", de->d_name) > (int)(size - len)) {
            path[len] = '\0';
            printf("Path too long: %s/%s\n", path, de->d_name);
            continue;
        }
        stat(path, &sfile);
        if (S_ISDIR(sfile.st_mode) && strcmp(de->d_name, ".") != 0) {
            //printf("This is a directory called %s\n", path);
            total = total + du_function(path, size);
        } else
        if (S_ISREG(sfile.st_mode) || strcmp(de->d_name, ".") == 0) {
            //printf("Size in bytes = %ld\n", (long)sfile.st_size);
            total = total + sfile.st_size;
            //printf("The total is %ld bytes so far.\n", total);
        }
    }
    path[len] = '\0';
    printf("%ld\t%s\n", total, path);
    closedir(dr);
    return total;
}

int main(int argc, char *argv[]) {
    char path[1024] = ".";
    if (argc > 1) {
        strcpy(path, argv[1]);
    }
    du_function(path, sizeof path);
    return 0;
}
0 голосов
/ 11 марта 2019

char cwd[1] = "."; слишком мало для строки .Нет места для символа null .

Используйте [] и позвольте компилятору определить необходимый размер для строки .

char cwd[] = ".";

stat() вызов основан на локальном имени, а не на полном пути.

#if 0
    stat(de->d_name, &sfile);
#else
    char buf[500];
    snprintf(buf, sizeof buf, "%s/%s", direc, de->d_name);
    stat(buf, &sfile);
#endif

Аналогичное нахождение в (удалено) @ PSkocik


Возможносуществуют другие проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...