Linux C递归统计目录及子目录文件数时目录打开报错如何解决
问题原因与修复方案
核心报错原因
你遇到的fail to open dir: No such file or directory错误核心来源于路径拼接逻辑错误:
现有代码拼接子目录路径时,没有在父目录路径和子目录名之间添加路径分隔符/:
sprintf(path,"%s%s/",root,ptr->d_name);
举个实际例子:如果父目录路径是/home/jesse/test,遍历到的子目录名是docs,原代码拼接后会生成非法路径/home/jesse/testdocs/,系统找不到该路径自然抛出不存在的错误。
其他需要调整的优化点
- 替换不安全的
sprintf为snprintf,避免路径长度超过MAXPATHLEN时触发缓冲区溢出 - 建议不要在递归函数中直接调用
exit,子目录打开失败直接终止整个程序的逻辑不够友好,可根据需求改成返回错误值由上层逻辑处理 DT_DIR类型判断依赖文件系统支持,部分特殊文件系统(如FAT、sysfs)可能不会返回正确的d_type,如果需要更高兼容性可以额外调用stat判断文件类型
修正后的代码
#include <stdio.h> #include <dirent.h> #include <string.h> #include <errno.h> #include <stdlib.h> #include <stdbool.h> #include <sys/param.h> // 补充缺失的isHidden函数实现 static int isHidden(const char *name) { return name[0] == '.' ? 1 : 0; } int countfiles(char *root, bool a_flag) { DIR *dir; struct dirent * ptr; int total = 0; char path[MAXPATHLEN]; int root_len = strlen(root); dir = opendir(root); if(dir == NULL) { perror("fail to open dir"); // 如果不需要直接退出可以改成 return -1; 上层判断返回值处理错误 exit(1); } errno = 0; while((ptr = readdir(dir)) != NULL) { if(strcmp(ptr->d_name,".") == 0 || strcmp(ptr->d_name,"..") == 0) { continue; } if(ptr->d_type == DT_DIR) { // 修正路径拼接逻辑,增加父目录和子目录之间的/ // 判断root末尾是否已经带/,避免拼接出重复斜杠 if (root[root_len - 1] == '/') { snprintf(path, MAXPATHLEN, "%s%s/", root, ptr->d_name); } else { snprintf(path, MAXPATHLEN, "%s/%s/", root, ptr->d_name); } total += countfiles(path, a_flag); } if(ptr->d_type == DT_REG) { if(a_flag){ total++; } else { if (isHidden(ptr->d_name) == 0){ total++; } } } } if(errno != 0) { perror("fail to read dir"); exit(1); } closedir(dir); return total; }
内容的提问来源于stack exchange,提问作者Jesse
相关产品推荐
相关产品推荐

