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

时间:2014-10-18 06:18:22

标签: c size byte long-integer 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 %s\n", path);
    }    
    stat(path, &statBuffer);
    if(strcmp(path, ".") == 0) {
        printf("%lld .\n", (long long)statBuffer.st_size);
    }   else {
            printf("%lld %s\n", (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 %s\n", 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] = '\0';
    strcpy(result, size);
    return TRUE;
}

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

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

  • 在调用bytesToKbytes
  • 之前,您不会预先加载任何结果
  • 如果尺寸小于99999
  • ,则不测试返回值以在结果中写入任何内容

您可以使用:

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 %s\n", result, path);
    return TRUE;
}

如果大小小于99999,您还可以更改bytesToKbytes以将字节长度放入结果中