如何修复“在C中递归打印子目录”

时间:2019-09-09 06:26:01

标签: c unix directory

我的当前目录中有以下文件/目录。 test_folder1是一个目录,该目录中还有一个目录。我的C代码应该递归打印当前目录中的所有文件/目录。但是,它仅显示当前目录和下一级子目录,不会超出该范围。请帮忙。


当前目录:

a.out    at.c     dt    dt.c    main.c    README    test.c    test_folder1.

test_folder1的子目录:

ahmet.txt  mehmet.txt  test_folder2.

test_folder2的子目录:

mahmut.txt

这对于mac终端C代码。

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

void depthFirst(DIR *dir){
  struct dirent *sd;
  char path[PATH_MAX];

  if(dir == NULL){
    printf("Error, unable to open\n");
    exit(1);
  }

  while( (sd = readdir(dir)) != NULL){
    if(strcmp(sd->d_name, ".") != 0 && strcmp(sd->d_name, "..") != 0){
      printf("%s\n", sd->d_name);
      realpath(sd->d_name,path);

      if(isdirectory(path)){
        depthFirst(opendir(sd->d_name));
      }               
    }
  }
}

int isdirectory(char *path) {
  struct stat statbuf;
  if (stat(path, &statbuf) == -1)
    return 0;
  else
    return S_ISDIR(statbuf.st_mode);
}

int main(int argc, char *argv[]){
  if(argc<2){
    printf("No arguments");
    DIR *dir;
    dir = opendir(".");
    depthFirst(dir);
    closedir(dir);
  }

这是输出

README
main.c
test.c
test_folder1
ahmet.txt
mehmet.txt
test_folder2
a.out
at.c
dt
dt.c

2 个答案:

答案 0 :(得分:3)

在您为realpath(sd->d_name, path)调用test_folder2时,您当前的工作目录仍然是.而不是test_folder1,因此realpath()正在使用./test_folder2,而不是./test_folder1/test_folder2

因此,path是可能的./test_folder2而不是./test_folder1/test_folder2的绝对路径,因此您的stat()调用失败,这意味着{{1 }}不是目录,因此没有为其使用test_folder2

您需要做的是:

  • 进入depthFirst()后,将当前工作目录(depthFirst())保存在某个局部变量中,然后将目录(getcwd())更改为您具有参数的目录。
  • 退出chdir()之前,将目录更改回先前的工作目录。

您可能希望让depthFirst()作为字符串接收路径,并自行进行depthFirst()调用。

答案 1 :(得分:1)

假设您具有以下结构(程序在dir_origin之外以dir_origin作为参数):

dir_origin
    README.md
    dir_p0:
        file1.txt
        dir_p1:
            file_1_1.txt
            file_1_2.txt
        dir_p2:
            single.txt
    some_other_files.txt

此时(第一次递归调用):

if(isdirectory(path)){
                                depthFirst(opendir(sd->d_name));

您正尝试在dir_p0上进行操作,但是该过程仍在目录dir_origin/..中进行,因此您需要输入要首先处理的目录的父目录(即{{1 }}),您可以通过在每次递归调用dir_origin之前在父目录上调用chdir来完成此操作,并在递归调用后通过使用{{ 1}}

避免更改工作目录的另一种解决方案是通过在递归调用之前加入当前路径,文件分隔符(depthFirst())和要处理的子目录来保持为子目录构建完整路径。