2011-08-12 86 views
2

我正在研究POSIX C学习练习,它涉及递归列出指定目录中的文件/文件夹。该程序接受一个或多个目录的参数。我可以列出初始目录的内容,但是递归存在问题。我在递归函数调用的参数中传递的方式有问题吗?Unix 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; 
} 

回答

2

打开警告将显示您在进行递归函数调用时传递错误的类型。我只需简单地使listdir采用char *参数而不是char **,然后在main中使用for循环来循环多个参数(如果需要的话)。

5

struct dirent的的d_name构件是有问题的项目的基本名称。所以,如果你正在经历一个目录是这样的:

. 
.. 
where-is/ 
    pancakes/ 
     . 
     .. 
     house 

一旦你where-is的时候,你会尝试listdir("pancakes")但不会工作,因为你需要listdir("where-is/pancakes")

您需要将它与您正在查找的目录名称结合起来,然后才能将其传递给下一个listdir调用。

你要替换类似这样的事情:

listdir(mydirent->d_name); 

有这样的事情:

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); 

或者,你可以chdir到目录中,当你进入他们,然后chdir备份当你完成。

2

您应该使用ftw为此,它调用子树的每个项目上的给定回调。这样,你可以避免自己使用明确的递归,并且你的代码会变得更短。