我正在开发一个项目,该项目应该打印出目录中所有文件的所有文件路径以及C中的所有子目录。基本上,它最终意味着模拟查找实用程序在Linux中。
我有以下代码:
void read_sub(char * sub_dir){
DIR *sub_dp = opendir(sub_dir);//open a directory stream
struct dirent * sub_dirp;//define
struct stat buf;//define a file status structure
char temp1[]=".";
char temp2[]="..";
char temp3[]="/";
if(sub_dp!=NULL){ //Check if the directory opened successfully
while((sub_dirp=readdir(sub_dp))!=NULL){ //until we've read every entry one by one
char * temp = sub_dirp -> d_name; //get the name
if(strcmp(temp, temp1)!=0 && strcmp(temp, temp2)!=0){ //Ignores . and .. in the directory
char *temp_sub = temp3; // This is '/'
temp_sub = strcat(temp_sub, temp); // Adds '/' before the name of the entry
//now you can add the / in front of the entry's name
char* temp_full_path=malloc(sizeof(char)*2000); //Create a variable to hold the full path
//Place the passed directory at the front of the path and add the name of the file to the end
temp_full_path=strcpy(temp_full_path,sub_dir);
strcat(temp_full_path,temp_sub);
//try to open the file path we just created
DIR * subsubdp = opendir(temp_full_path);
//if not null, we've found a subdirectory, otherwise it's a file
if(subsubdp!=NULL){
//close the stream because it'll be reopened in the recursive call.
closedir(subsubdp);
read_sub(temp_full_path);//call the recursive function call.
}else{
printf("%s\n",temp_full_path);
}
}
}//end of while loop
closedir(sub_dp);//close the stream
}else{
printf("cannot open directory\n");
exit(2);
}
}
我通过直接传递它" testdir"来运行它,这是一个具有以下结构的目录:
testdir/
|-- dir1
| |-- dir2
| | |-- test5
| | `-- test6
| |-- test3
| `-- test4
|-- dir3
| |-- test7
| `-- test8
|-- test1
`-- test2
因此,它应输出如下内容:
testdir/dir1/dir2/test5
testdir/dir1/dir2/test6
testdir/dir1/test3
testdir/dir1/test4
等等。但是,实际结果是:
testdir/dir1/dir2/test6
testdir/dir1/dir2/test6test5
testdir/dir1/dir2test3
testdir/dir1/dir2test3test4
testdir/dir1test1
testdir/dir1test1dir3
testdir/dir1test1dir3test2
所以看起来它可能无法在运行时正确清除完整的文件路径?此外,它似乎并没有真正进入dir3来打印test7和test8。我做错了什么?谢谢。
答案 0 :(得分:1)
您没有为目标字符串分配足够的空间。您至少需要char temp1[PATH_MAX] = ".";
char temp2[PATH_MAX] = "..";
char temp3[PATH_MAX] = "/";
个字节。
尝试
snprintf()
实际上,编译器只会分配足够的空间来保存初始化字符串(2,3,2)。所以你的程序表现出不确定的行为。我建议使用strcat()
代替strcat()
,因为它是直接的而不是昂贵的。每次调用'\0'
时,它将搜索目标字符串的当前结尾,直到找到终止{{1}}。
此外,尝试使用最少数量的缩进级别,因为代码很快变得非常难以理解。
答案 1 :(得分:0)
您可以使用S_ISDIR
来测试目录。应使用malloc
清除free
以避免内存泄漏。在递归函数中实现malloc/free
会变得太复杂,因此最好只声明一个临时缓冲区path[4096]
。只要路径名不太长,这就可以工作。如果路径太长,那么最安全的选择是打印错误而不是继续。
对于"."
和".."
,您可以声明
const char *temp1 = ".";
const char *temp2 = "..";
这样可以避免意外地写入temp1
和temp2
。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
void read_sub(char *subdir)
{
DIR *dirp = opendir(subdir);
if (!dirp)
return;
struct dirent *dentry;
while ((dentry = readdir(dirp)) != 0)
{
if (strcmp(dentry->d_name, ".") == 0 || strcmp(dentry->d_name, "..") == 0)
continue;
printf("%s/", subdir);
char path[4096];
int len = strlen(subdir) + 1 + strlen(dentry->d_name) + 1;
if (len >= sizeof(path))
{
printf("path is too long...\n");
break;
}
sprintf(path, "%s/%s", subdir, dentry->d_name);
struct stat st;
stat(path, &st);
if (S_ISDIR(st.st_mode))
{
printf("%s\n", dentry->d_name);
read_sub(path);
}
else
{
printf("%s\n",dentry->d_name);
}
}
closedir(dirp);
}
或者,您可以为path
int len = strlen(subdir) + 1 + strlen(dentry->d_name) + 1;
char path[len];
sprintf(path, "%s/%s", subdir, dentry->d_name);