如何获取C中子目录的总大小?

时间:2014-02-07 02:39:09

标签: c recursion size stat subdirectory

有没有办法让子目录的总大小具有递归性?

例如:

Dir1
-- FileA.txt (90)
-- SubDir2 (4096)
---- FileB.txt (100)
---- FileC.txt (400)

当我试图获得SubDir2的大小时,它给了我4186.我希望得到的预期答案是4596.

我的程序计算FileA的大小而不是FileB和FileC。如何计算FileB和FileC?

首先,我必须使用这些标题:

#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>

然后,我使这个函数递归地调用它:

static DIR *dir;

void goDir(char* argv[])
{
    struct dirent *dit;
    struct stat st;

    int size = 0;
    static int total_size = 0;

    char filePath[NAME_MAX];

    while ((dit = readdir(dir)) != NULL)
    {
        sprintf(filePath, "%s/%s", argv[1], dit->d_name); // To show correctly the size and name of files
        lstat(filePath, &st);
        // To skip . and ..
        if ( (strcmp(dit->d_name, ".") == 0) || (strcmp(dit->d_name, "..") == 0) ) continue;

        size = st.st_size;

        if(S_ISDIR(st.st_mode))
        {   
            goDir(argv); // For Recursivity 

            total_size += size;

            printf("DIR\t");            
            printf("MODE: %lo\t", (unsigned long) st.st_mode);
            printf("SIZE: %d\t", total_size);
            printf("%s\n", dit->d_name);
        }
        else
        {
            total_size += size;

            printf("FILES\t");
            printf("MODE: %lo\t", (unsigned long) st.st_mode);
            printf("SIZE: %d\t", size);
            printf("%s\n", dit->d_name);
        }

    }

}

然后,我的主要计划:

int main (int argc, char *argv[])
{
    if ( argc != 2 ) {
        printf("Usage: Program <Directory>\n");
        return 1;
    }

    if ((dir = opendir(argv[1])) == NULL) return 1;

    goDir(argv);
    closedir(dir);

    return 0;
}

2 个答案:

答案 0 :(得分:2)

您的goDir()函数永远不会打开新目录,或者在完成后关闭目录。这将导致问题 - 基本上,您不会遍历目录层次结构。

您需要在dir函数中设置static个本地(非goDir())变量;你会打开和关闭目录;而不是传递argv,你将传递目录名等。

当您处于此状态时,您应该更改goDir()以返回找到的尺寸,并丢失static变量total_size

这段代码看似半合理:

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

#ifndef NAME_MAX
#define NAME_MAX 1024
#endif

static long goDir(char *dirname)
{
    DIR *dir = opendir(dirname);
    if (dir == 0)
        return 0;

    struct dirent *dit;
    struct stat st;
    long size = 0;
    long total_size = 0;
    char filePath[NAME_MAX];

    while ((dit = readdir(dir)) != NULL)
    {
        if ( (strcmp(dit->d_name, ".") == 0) || (strcmp(dit->d_name, "..") == 0) )
            continue;

        sprintf(filePath, "%s/%s", dirname, dit->d_name);
        if (lstat(filePath, &st) != 0)
            continue;
        size = st.st_size;

        if (S_ISDIR(st.st_mode))
        {
            long dir_size = goDir(filePath) + size;
            printf("DIR\t");
            printf("MODE: %lo\t", (unsigned long) st.st_mode);
            printf("SIZE: %ld\t", dir_size);
            printf("%s\n", filePath);
            total_size += dir_size;
        }
        else
        {
            total_size += size;
            printf("FILES\t");
            printf("MODE: %lo\t", (unsigned long) st.st_mode);
            printf("SIZE: %ld\t", size);
            printf("%s\n", filePath);
        }
    }
    return total_size;
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s <Directory>\n", argv[0]);
        return 1;
    }

    long size = goDir(argv[1]);
    printf("Total size: %ld\n", size);

    return 0;
}

它编译并运行。它没有给出与du -k相同的答案,主要是因为它没有将文件大小四舍五入到整数个磁盘块。您需要查看st_blksize中的st_blocks和/或struct stat才能获取该信息。

答案 1 :(得分:0)

您必须使用哈希表来跟踪inode的出现次数。这样他们就不会被计算两次了。