Linux递归遍历子目录搜索文件的代码报错问题求助
解决递归搜索文件时遇到非目录文件报错的问题
我懂你现在的困扰——递归搜索文件的时候,一碰到非目录的文件程序就报错停住,加了S_ISREG判断也没搞定对吧?这问题其实出在判断逻辑顺序和文件路径处理上,咱们一步步来修正:
问题根源分析
你遇到的报错,本质是对非目录文件调用了opendir()——这个函数只能打开目录,对普通文件调用肯定会失败,触发perror。而你加的S_ISREG判断没起作用,大概率是这两个原因:
- 没有先拼接完整文件路径就调用
stat(),导致获取文件属性失败,判断逻辑失效; - 判断的方向错了:我们需要筛选出目录去递归打开,而不是判断普通文件——普通文件只需要检查文件名是否匹配即可,不需要去打开它。
修正后的完整代码
下面是调整后的代码,我会标注关键修改点:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <dirent.h> #include <string.h> // 递归搜索函数:参数为当前目录路径,目标文件名 void search_file(const char *base_path, const char *target) { char full_path[1024]; // 存储完整文件路径,可根据需求调整大小 DIR *dir = opendir(base_path); struct dirent *entry; struct stat stat_buf; // 打开目录失败时,打印错误但不终止程序,继续搜索其他目录 if (!dir) { perror("Error opening directory"); return; } while ((entry = readdir(dir)) != NULL) { // 跳过当前目录(.)和上级目录(..),避免无限递归 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; // 拼接当前目录与子项的完整路径,这是关键! snprintf(full_path, sizeof(full_path), "%s/%s", base_path, entry->d_name); // 获取文件属性,失败则跳过该文件,继续处理下一个 if (stat(full_path, &stat_buf) == -1) { perror("Error getting file stat"); continue; } // 如果是目录,递归搜索该子目录 if (S_ISDIR(stat_buf.st_mode)) { search_file(full_path, target); } // 如果是普通文件,检查是否是目标文件 else if (strcmp(entry->d_name, target) == 0) { printf("Found target file: %s\n", full_path); } } closedir(dir); } int main(int argc, char *argv[]) { // 检查参数是否正确:需要传入起始目录和目标文件名 if (argc != 3) { fprintf(stderr, "Usage: %s <start_directory> <target_filename>\n", argv[0]); exit(EXIT_FAILURE); } // 调用递归搜索函数 search_file(argv[1], argv[2]); return 0; }
关键修改说明
- 完整路径拼接:用
snprintf把当前目录和子项名称拼成完整路径,确保stat()和递归调用时能正确定位文件; - 正确的类型判断:用
S_ISDIR筛选目录,只有目录才会递归调用opendir(),普通文件只做文件名匹配; - 容错处理:打开目录或获取文件属性失败时,用
return或continue跳过,而不是直接终止程序,保证其他目录的搜索能继续; - 跳过特殊目录:必须跳过
.和..,否则会陷入无限递归。
这样修改后,程序就不会因为碰到普通文件而报错停止,能正常递归遍历所有子目录并找到目标文件啦。
内容的提问来源于stack exchange,提问作者sylar12
相关产品推荐
相关产品推荐

