C-递归调用遍历子目录并打印所有文件+大小(使用stat)



我有一个程序,它递归地打印cwd大小加上包含的文件大小,并为每个子目录重复。


递归目录遍历函数:(请注意,在这个函数中使用printf并传递两个字符串的原因是输出需要采用特殊格式,这样我就不能只输出实际的文件路径。此外,我正在学习使用ubuntu中目录的系统调用,所以如果你对代码的改进有任何意见,我将不胜感激。)(风格或使用更简单的东西来完成同样的事情)。

#include <sys/stat.h>
#include <limits.h>
#include <dirent.h>
#include <libgen.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define TRUE 1 
#define FALSE 0
#define FIRST_ARG 1
#define SECOND_ARG 2
char* fileName;
FILE* fileToRead;
DIR* directoryToRead;
int printFileSize(char*);
int printWorkingSize(char*, char*);
int printSize(char*, char*);
int printDir(char*, char*);
int printCurrentDir(char*, char*);
int bytesToKbytes(long long, char*);
int main(int argc, char** argv) {
    if(argc == FIRST_ARG) {
        char currentDir[PATH_MAX + 1] = "";
        char* currentDirectory;
        directoryToRead = opendir (".");
        if (directoryToRead == NULL){
            exit (EXIT_FAILURE);
        }
        closedir(directoryToRead);
        printCurrentDir(currentDirectory, ".");
    }
return 0;
}
int printCurrentDir(char* name, char* path) {
    struct dirent *dir;
    struct stat statBuffer;
    char fileName[PATH_MAX + 1];
    char filePath[PATH_MAX + 1];
    DIR* openDir;
    if((openDir = opendir(path)) == NULL) {
        printf("Could not open %sn", path);
    }    
    stat(path, &statBuffer);
    if(strcmp(path, ".") == 0) {
        printf("%lld .n", (long long)statBuffer.st_size);
    }   else {
            printf("%lld %sn", (long long)statBuffer.st_size, name);
    }
    while (TRUE) {  // go through contents of current directory
        dir = readdir(openDir);
        if(!dir) {
            break;
        }
        if((strcmp(dir->d_name, "..") == 0) || (strcmp(dir->d_name,".") == 0)) {
            continue;
        }
        if(name == NULL) {
            strcpy(fileName, dir->d_name);
        } else {
        strcpy(fileName, name);
        strcat(fileName, "/");
        strcat(fileName, dir->d_name);
        }
        strcpy(filePath, path);
        strcat(filePath, "/");
        strcat(filePath, dir->d_name);
        if(dir->d_type == DT_DIR) {  // if the next file is a directory
            if(!printCurrentDir(fileName, filePath)) {
                return FALSE;
            }
        } 
        else if(!printWorkingSize(fileName, filePath)) {
            return FALSE;
        }
    }
    return TRUE;
}
//output file size in bytes followed by name-> (char* file)
int printWorkingSize(char* file, char* path) {
    struct stat statBuffer;
    stat(path, &statBuffer);
    char result[PATH_MAX];
    if(bytesToKbytes((long long)statBuffer.st_size, result) == FALSE) {
        sprintf(result, "%lld", (long long)statBuffer.st_size);
    }
    printf("%5s %sn", result, path);
    return TRUE;
        }

// convert bytes to kilobytes if more than 5 digits
int bytesToKbytes(long long bytes, char* result) {
    if(!(bytes > 99999)) {
        return FALSE;
    }
    char size[PATH_MAX];
    sprintf(size, "%lld", bytes);
    size[3] = 'K';
    size[4] = '';
    strcpy(result, size);
    return TRUE;
}

它是特定于操作系统的。在Linux和POSIX上,您应该简单地使用nftw(3)库函数,该函数递归地读取目录并已经为您调用stat(2)。

问题在于使用bytesToKbytes的方式。它返回一个布尔值来指示它是否在结果中写入了任何内容,并且:

  • 在调用bytesToKbytes之前,不在result中预加载任何内容
  • 如果大小小于99999,则不测试返回值以在resul中写入任何内容

您可以使用:

int printWorkingSize(char* file, char* path) {
    struct stat statBuffer;
    stat(path, &statBuffer);
    char result[PATH_MAX];
    if (! bytesToKbytes((long long)statBuffer.st_size, result)) {
        sprintf(result, "%lld", (long long)statBuffer.st_size);
    }
    printf("%5s %sn", result, path);
    return TRUE;
}

如果大小小于99999

,您也可以更改bytesToKbytes以将长度(以字节为单位)放入resul

最新更新