【问题标题】:Recursively counting files and all directories given the directory递归计算给定目录的文件和所有目录
【发布时间】:2020-06-08 20:41:55
【问题描述】:

我一直在做这个项目,但我被困在这段代码中的一行。

这基本上通过在UNIX 环境中使用C++ 的目录递归地计算文件和目录数,但是每当我进行递归调用时,它都会出现错误提示:

Segmentation fault (core dumped)

我以为是因为我没有检查“。”和“..”但不是这样。

递归调用有什么问题吗?

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

using namespace std;


void cntFile(string it, int &reg, int &der, size_t &size)
{
    DIR * dirp;
    struct dirent *entry;
    struct stat file_stats;

    dirp = opendir(it.c_str());
    while ((entry = readdir(dirp)) != NULL)
    {
        if (entry->d_type == DT_REG)
        {
            reg++;
            stat(getcwd(entry->d_name,sizeof(entry->d_name)), &file_stats);
            size += (unsigned int) file_stats.st_size;

        }
        else if (entry->d_type == DT_DIR)
        {  

           if(string(entry->d_name) != ".." | string(entry->d_name) != ".")
            {
                string temp;
                temp.append(it + entry->d_name + "/");
                cntFile(temp, reg, der, size);
            }
           der++;
        }
    }
    closedir(dirp); 
}

int main (void)
{
    int reg = 0;
    int der = 0;
    size_t size = 0;
    string it = "/usr/share/";
    cntFile(it, reg, der, size);
    printf("The total number of directories in directory is %d \n", reg);
    printf("The total number of files in directory is %d \n", der);
    printf("The total number of bytes occupied by all files in directory is %zu\n", size);
    return 0;
}

【问题讨论】:

  • 如果您的编译器和标准库实现足够新,那么我建议您使用std::filesystem 来满足您的所有文件系统需求。 Recursive directory iteration 一下子变得很轻松了。
  • 是的,这是一个错误!感谢您的帮助:)
  • string(entry-&gt;d_name) != ".." | string(entry-&gt;d_name) != "." 我猜你的意思是string(entry-&gt;d_name) != ".." &amp;&amp; string(entry-&gt;d_name) != "."?注意不仅是按位运算的变化,还有逻辑 AND 的变化。我建议您了解有关否定条件的 De Morgan's laws

标签: c++ unix recursion directory


【解决方案1】:

在如何使用readdir 及其返回指针的结构方面存在一个主要问题。

来自上面链接的参考:

应用程序不得修改readdir()的返回值所指向的结构,也不得修改结构内指针所指向的任何存储区域。

而这正是您在调用getcwd 时所做的,修改结构成员d_name 的内容。

如果您想修改d_name 中名称的内容,您需要创建自己的本地副本并使用它。

【讨论】: