如何使用递归获得C中文件夹的总大小?

时间:2014-02-05 05:48:55

标签: c recursion directory size stat

所有文件夹的大小均为4096 B.

如何获取包含所有文件大小的文件夹的总大小?

例如:

> Dir1 (4096)
> -- File1.txt (100)
> -- Dir 2 (4096)
> ---- File2.txt (100)

当我试图获得Dir1的大小时,它给了我4096。 我希望得到的预期答案是8392

另一个例子:

DirA (4096)
-- FileA (100)
-- FileB (100)

总数应为4296

我正在试图找出算法,但我找不到一种方法来检测它是否是一个文件夹。对不起,下面的“粗俗”代码......

DIR *dir;
struct dirent *dp;
struct stat fileStat;
    int getTotalDirSize()
    {
        while()
        {
            if(/*Detect Folder/Directory*/)
            {
            totalSize += 4096;
                getTotalDirSize();
            }
            else
            {
                totalSize += fileSize;
            }

        }

        return totalSize;
    }

注意:我正在使用struct stat来获取大小和文件/文件夹名称。

2 个答案:

答案 0 :(得分:5)

它使用stat工作,但只有你必须做的是提供完整的状态路径,如你的例子Dir1-> 4096B那样,如果你想知道{{1}的大小像这样使用stat:

File1.txt

然后在stat中使用strcpy(str,Dir1); //str is a string strcat(str,"/"); strcat(str,filename); 来获取该文件的大小。我想在这里你必须使用 dirent structure 和DIR作为文件夹及其内容。

查找 dirent structure 指针的文件夹使用str。对于递归操作,将所有函数放在一个单独的函数中,并递归调用它直到文件夹搜索完成。

d_type = 4

答案 1 :(得分:1)

我正在寻找解决这个问题的方法,当我遇到这个线程时,其他一些人在这里处理相同或类似的问题(我在最后发现3个不同的代码旨在计算一个文件夹的总大小纯C)。不幸的是,它们都没有自己工作或者不完整,所以我不得不改进它们(将一个合并到另一个)并且我得到了以下完整且有效的代码和示例(应该放在main.c文件中,确切的文件夹已更改,然后运行)。我希望它有所帮助!

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

int readFolderSize(int* totalSize, char* folder)
{
    char fullPath[256];
    struct dirent *dirData;
    struct stat buffer;
    int exists;
    DIR *poDir;
    int resp = EXIT_SUCCESS;

    poDir = opendir(folder);

    if (poDir == NULL)
    {
        perror("general_getFolderSize: poDir fail!");

        return EXIT_FAILURE;
    }

    while ((dirData = readdir(poDir)))
    {
        if (dirData == NULL)
        {
            const unsigned int err = errno;

            fprintf(stderr, "general_getFolderSize: Failed in readdir (%u)\n",err);

            resp = EXIT_FAILURE;

            continue;
        }

        //
        if (dirData->d_type == DT_DIR)
        {
            if (dirData->d_name[0] != '.')
            {
                //printf("general_getFolderSize: Is a directory: %s\n", dirData->d_name);

                strcpy(fullPath,folder);
                strcat(fullPath,"/");
                strcat(fullPath,dirData->d_name);

                //printf("general_getFolderSize: Accessing dir: %s\n", fullPath);

                if (readFolderSize(totalSize,fullPath) == EXIT_FAILURE)
                    resp = EXIT_FAILURE;
            }
        }
        else
        {
            strcpy(fullPath,folder);
            strcat(fullPath,"/");
            strcat(fullPath,dirData->d_name);

            exists = stat(fullPath,&buffer);

            if (exists < 0)
            {
                const unsigned int err = errno;

                fprintf(stderr, "general_getFolderSize: Failed in stat (file) %s: %u\n", fullPath,err);

                resp = EXIT_FAILURE;

                continue;
            }
            else
            {
                (*totalSize) += buffer.st_size;

                //printf("general_getFolderSize: Item size (file) (%s): %d\n",fullPath,(int)buffer.st_size);
            }
        }
    }

    closedir(poDir);

    return resp;
}

/*!
 * \brief general_getFolderSize returns the size of a folder in bytes.
 * \param folder is the name of the folder (preferentially without a '/' at the end)
 * \param totalSize is a pointer where the result value is given
 * \return
 */
int general_getFolderSize(char* folder, int* totalSize)
{
    printf("general_getFolderSize: Start\n");

    //
    if (readFolderSize(totalSize,folder) == EXIT_FAILURE)
    {
        perror("general_getFolderSize: Call to readFolderSize failed!");

        return EXIT_FAILURE;
    }

    //
    printf("general_getFolderSize: Stop\n");

    return EXIT_SUCCESS;
}

int main()
{
    int folderSize;

    if (general_getFolderSize("/home/maiquel/Documents/TEMP/maindir",&folderSize) == EXIT_FAILURE)
    {
        printf("Error reading folder size!");
    }
    else
    {
        printf("Folder size: %d b (%d kb / %d Mb)\n", folderSize, folderSize/1024, folderSize/(1024 * 1024));
    }

    return EXIT_SUCCESS;
}

Ps:虽然我知道EXIT_SUCCESSEXIT_FAILURE不应该用作函数返回值,但我更喜欢这样做,而不是在代码名称中创建新的定义简单。