如何递归列出所有目录?

时间:2016-04-02 15:29:57

标签: c linux

我的代码无效。我需要显示作为命令行参数给出的目录中的所有目录。到目前为止,我已经尝试过这个:

#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>

struct stat my_stat;

int searchDirectory (char *dirName);

int searchDirectory(char *dirName){
    struct dirent *pDirent;
    DIR *pDir;

    pDir = opendir(dirName);
    if (pDir == NULL) {
        printf("Cannot open directory '%s'\n", dirName );
        return 1;
    }

    while ((pDirent = readdir(pDir)) != NULL){
        printf("%s\n", pDirent->d_name);
        stat(pDirent->d_name, &my_stat);
        if (S_ISDIR(my_stat.st_mode)){
            searchDirectory(pDirent->d_name);
            printf("Directory Found: %s\n", pDirent->d_name);
        }
    }

    return 0;
}

int main(int argc, char *argv[]){
    struct stat my_stat;


    if (lstat(argv[1], &my_stat) < 0){
        perror("stat error");
    }

    if (S_ISDIR(my_stat.st_mode)){ 
        printf("Directory found\n");
        searchDirectory(argv[1]);
    }

    return 0;
}

我不确定为什么但由于某种原因我的代码正在将普通文件作为目录读取,但是S_ISDIR(my_stat.st_mode))应该阻止这一点。什么可能是错的?

2 个答案:

答案 0 :(得分:2)

您遇到的问题是pDirent->d_name与您当前列出的目录相关,而您处理的目录中包含启动流程的工作目录。

要修复,请在执行opendir

之前连接目录的名称
int searchDirectory(char *dirName){
    ......
    while ((pDirent = readdir(pDir)) != NULL){
        printf("%s\n", pDirent->d_name);
        stat(pDirent->d_name, &my_stat);
        if (S_ISDIR(my_stat.st_mode)){
            // construct new path ....
            char * dirname = malloc(strlen(dirName)+strlen(pDirent->d_name)+2);
            strcat(strcat(strcpy(dirname,dirName),"/"),pDirent->d_name);
            searchDirectory(dirname);
            free(dirname)
            printf("Directory Found: %s\n", pDirent->d_name);
        }
     }
     .....

另请注意,您需要将...目录作为特殊情况处理,否则您的代码最终将无限递归,因此您需要额外的代码来处理这些 - 请参阅this question了解详情

答案 1 :(得分:1)

您对searchDirectory(pDirent->d_name);的递归调用是错误的,因为您有一个相对于您正在解析的目录的名称,因此您需要连接您实际正在解析的目录的名称和相对(到该目录)的名称你有:

char newDir[PATH_MAX];
snprintf(newDir,PATH_MAX,"%s/%s",dirName,pDirent->d_name);
searchDirectory(newDir);