【问题标题】:Count the number of files in, and below a directory in Linux C recursively递归计算Linux C中目录中和目录下的文件数
【发布时间】:2023-11-06 21:08:01
【问题描述】:

我编写了一个函数来计算目录中和目录下的文件数(包括子目录中的文件)。 但是,当我在具有子目录的目录上测试代码时,它总是报告错误说:“无法打开目录:没有这样的文件或目录”。 有什么办法可以让它发挥作用吗?

int countfiles(char *root, bool a_flag)//a_flag decide if it including hidden file
{
    DIR *dir;
    struct dirent * ptr;
    int total = 0;
    char path[MAXPATHLEN];
    
    dir = opendir(root); //open root dirctory
    if(dir == NULL)
    {
        perror("fail to open dir");
        exit(1);
    }
    
    errno = 0;
    while((ptr = readdir(dir)) != NULL)
    {
        //read every entry in dir
        //skip ".." and "."
        if(strcmp(ptr->d_name,".") == 0 || strcmp(ptr->d_name,"..") == 0)
        {
            continue;
        }
       
        //If it is a directory, recurse
        if(ptr->d_type == DT_DIR)
        {
            sprintf(path,"%s%s/",root,ptr->d_name);
            //printf("%s/n",path);
            total += countfiles(path, a_flag);
        }
        
        if(ptr->d_type == DT_REG)
        {
            if(a_flag == 1){
            total++;
            }
            else if (a_flag == 0){
                if (isHidden(ptr->d_name) == 0){
                    total++;
                }
            }
        }
    }
    if(errno != 0)
    {
        printf("fail to read dir");
        exit(1);
    }
    closedir(dir);
    return total;
}

【问题讨论】:

  • 如果你取消注释//printf("%s/n",path);这行会显示什么?
  • 打印 dir 和 ls 的简单案例的结果,并与您的调试输出进行比较。您是否尝试将文件作为目录打开?您是否要打开不完整的路径?这里有很多可能的新手错误

标签: c linux


【解决方案1】:

有什么我可以让它工作的吗?

当然,很多。就我个人而言,我会首先使用正确的接口来处理这些东西,在 Linux 和 POSIXy 系统中是nftw()。这将导致程序不仅更短、更有效,而且如果有人同时重命名正在扫描的树中的目录或文件,也不会那么容易混淆。

程序员几乎从来没有像nftw()scandir()glob()fts family of functions 那样健壮和高效地实现 opendir()/readdir()/closedir()。为什么老师们在这个时代仍然坚持使用过时的 *dir() 函数,这让我感到困惑不已。

如果你必须使用 *dir 函数,因为你的老师不知道 POSIX 并且希望你使用你在现实生活中不应该使用的接口,那么看看你如何构建新目录的路径:sprintf()线。甚至可以将它 (path) 打印出来,您可能会自己找到解决方法。

即使那样,sprintf() 在现实生活中的程序中也是不允许的(因为当参数长于预期时,它会导致静默缓冲区溢出;而这可能发生在 Linux 中,因为实际上没有路径长度的固定限制)。您应该至少使用 snprintf() 并检查其返回值是否溢出,或者在 Linux 中,asprintf() 会动态分配结果字符串。

【讨论】: