C中的目录遍历
Posted
技术标签:
【中文标题】C中的目录遍历【英文标题】:Directory traversing in C 【发布时间】:2015-06-30 07:59:13 【问题描述】:我试图搜索这个问题,但找不到令人满意的答案。所以这是我的问题:
我正在遍历具有以下代码变体的目录:
我。
#include<stdio.h>
#include<sys/types.h>
#include<dirent.h>
#include<string.h>
#include<sys/stat.h>
void traverseDirectory(char name[100])
DIR* dir;
struct dirent *ent;
struct stat states;
dir = opendir(name);
while((ent=readdir(dir)) != NULL)
stat(ent->d_name,&states);
if(!strcmp(".", ent->d_name) || !strcmp("..", ent->d_name))
continue;
else
printf("%s/%s\n",name,ent->d_name);
if(S_ISDIR(states.st_mode))
strcat(name,"/");
strcat(name,ent->d_name);
traverseDirectory(name);
closedir(dir);
int main()
char path[100];
printf("Enter the path:\n");
scanf("%s",&path);
traverseDirectory(path);
这个遍历子目录,但在遍历第一个子目录并打印其文件后出现分段错误。
输出是:
Enter the path:
/home/harshad/dump
/home/harshad/dump/TraverseDirectory.c
/home/harshad/dump/temp
/home/harshad/dump/temp/temptest.txt
Segmentation fault
二。
#include<stdio.h>
#include<sys/types.h>
#include<dirent.h>
#include<string.h>
#include<sys/stat.h>
void traverseDirectory(char name[100])
DIR* dir;
struct dirent *ent;
struct stat states;
dir = opendir(name);
while((ent=readdir(dir)) != NULL)
stat(ent->d_name,&states);
if(!strcmp(".", ent->d_name) || !strcmp("..", ent->d_name))
continue;
else
printf("%s/%s\n",name,ent->d_name);
if(S_ISDIR(ent->d_type & DT_DIR))
strcat(name,"/");
strcat(name,ent->d_name);
traverseDirectory(name);
closedir(dir);
int main()
char path[100];
printf("Enter the path:\n");
scanf("%s",&path);
traverseDirectory(path);
这个打印给定目录中的所有文件和子目录,但不遍历子目录。它的输出是:
Enter the path:
/home/harshad/dump
/home/harshad/dump/TraverseDirectory.c
/home/harshad/dump/temp
/home/harshad/dump/TraverseDirectory1.out
/home/harshad/dump/dump
/home/harshad/dump/test.txt
/home/harshad/dump/SortMarks.c
/home/harshad/dump/TraverseDirectory.out
/home/harshad/dump/TraverseDirectoryTemp.out
/home/harshad/dump/TraverseDirectory1.c
/home/harshad/dump/TraverseDirectoryTemp.c
/home/harshad/dump/FindEven.c
这里的 dump 和 temp 是子目录,每个子目录都包含一些文件。首先,我认为由于用户权限,它可能无法遍历子目录(因为它们是由 root 创建和拥有的),但正如您在第一个程序的输出中看到的那样,情况并非如此。所以我无法找出这两个程序的问题。 P.S.:在前两行程序打印目录和文件之后的输出中。
【问题讨论】:
你试过用调试器单步调试代码吗? 通过阅读以下内容学习帮助自己:ericlippert.com/2014/03/05/how-to-debug-small-programs 【参考方案1】:您真的应该检查opendir()
中的错误。如果失败,它将返回NULL
,然后下一个readdir()
将出现seg-fault。
这可能就足够了:
dir = opendir(name);
if (!dir)
perror(name);
return;
【讨论】:
谢谢@rodrigo。它就像一个魅力。但我是 C 的新手,并不能真正理解条件的重要性。我认为这可能是递归调用的终止条件。但它确实避免了分段错误。你能解释一下如何以及为什么。 @harshad:您的IS_DIR
测试有时似乎会失败。这就是为什么(1)你得到/home/harshad/dump/temp/temptest.txt
(我假设它不是一个目录)和(2)下一次迭代中的opendir
失败(因为你告诉它打开一个非-现有目录)。 IS_DIR
可能会失败,因为你用错了。
@harshad:任何系统调用都可能失败,包括opendir()
、stat()
、readdir()
。这通常是一个编程错误,没有检查失败。有时忽略错误的后果是轻微的,有时却是致命的。如果是opendir()
,它会在失败时返回NULL
指针。并且使用NULL
指针是未定义的行为,但它通常会导致分段错误。更微妙的是您没有检查stat()
的失败,因为states
变量将未初始化...
@Jongware "temp/" 肯定是 "dump/" 目录中包含 "temptext.txt" 文件的子目录。而且我认为所有建议都指向类似的解决方案,即检查函数的返回值。所以我想现在我对代码中发生了什么以及正确的解决方案有一个清晰的认识。感谢您的帮助。【参考方案2】:
您将每个文件名连接到通过此传递的名称上:
strcat(name,ent->d_name);
但不为下一个文件撤消它。所以字符串变得越来越长,直到它打破它分配的大小。
您应该在本地构建另一个字符串,以保留传递的名称。
char localname[100];
strcpy(localname, name);
strcat(localname,"/");
strcat(localname,ent->d_name);
traverseDirectory(localname);
但错误保护比我用过的更好。
【讨论】:
是的,我发现了那个逻辑错误,但没有在问题中更新。我的错 :)!感谢您的帮助。以上是关于C中的目录遍历的主要内容,如果未能解决你的问题,请参考以下文章