我正在进行POSIX C学习练习,该练习涉及递归列出指定目录中的文件/文件夹。该程序作为一个或多个目录的参数。我可以列出初始目录的内容很好,但有一个递归问题。我在递归函数调用的参数中传递的方式有问题吗?
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
void listdir(char *argv[])
{
DIR *mydirhandle;
struct dirent *mydirent;
struct stat statinfo;
int n = 1;
while(argv[n] != NULL)
{
if((mydirhandle = opendir(argv[n])) == NULL)
{
perror("opendir");
exit(1);
}
printf("%s/\n", argv[n]);
while((mydirent = readdir(mydirhandle)) != NULL)
{
if((strcmp(mydirent->d_name, ".") == 0) || (strcmp(mydirent->d_name, "..") == 0))
{
continue;
}
else
{
printf("\t%s\n", mydirent->d_name);
//check if next entry is a directory
if(mydirent->d_type == DT_DIR)
{
//is current directory being passed correctly here?
listdir(mydirent->d_name);
}
}
}
n++;
closedir(mydirhandle);
}
}
int main(int argc, char *argv[])
{
if(argc < 2)
{
printf("usage: %s <directory>\n", argv[0]);
return 0;
}
listdir(argv);
return 0;
}
答案 0 :(得分:5)
d_name
的{{1}}成员是相关项目的基本名称。所以,如果你要浏览这样的目录:
struct dirent
进入.
..
where-is/
pancakes/
.
..
house
后,您会尝试where-is
,但这不起作用,因为您需要listdir("pancakes")
。
在您拥有可以传递给下一个listdir("where-is/pancakes")
电话的内容之前,您需要将其与您正在查看的目录的名称相结合。
你想要替换这样的东西:
listdir
有这样的事情:
listdir(mydirent->d_name);
或者,您可以在输入目录时chdir
进入目录,然后在完成后char *next_dir = malloc(strlen(argv[n]) + strlen(mydirent->d_name) + 1 + 1);
sprintf(next_dir, "%s/%s", argv[n], mydirent->d_name);
listdir(next_dir);
free(next_dir);
备份。
答案 1 :(得分:2)
启用警告将显示您在进行递归函数调用时传递了错误的类型。我只是让listdir
使用char *
参数而不是char **
,然后在main
中使用for循环来循环遍历多个参数(如果需要)。
答案 2 :(得分:2)
您应该使用ftw
,它会在子树的每个项目上调用给定的回调。这样,您就可以避免自己使用显式递归,并且您的代码会变得更短。