在 C 中递归打印 Linux 路径中的所有文件和文件夹

Printing all files and folders in a path in Linux, recursively, in C

我一直在尝试学习如何使用函数与系统上的路径交互,但我想我一开始就卡住了。

我特别搜索了 web 和 Whosebug,但找不到像我想做的那样的基本实现。还有一些其他的问题,和我的类似,但我觉得它们不像我的简单和初学者友好。

这是代码,这段代码只打印给定路径中的文件,以及“.”和“..”

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

void listdir(DIR *c);

int main()
{

    DIR* root_d;
    root_d = opendir("/home/foo/Desktop/testx");
    listdir(root_d);

}

void listdir(DIR *c){
    DIR* current = c;
    struct dirent *curr_ent;
    if((curr_ent =readdir(current)) != NULL && curr_ent->d_type == DT_DIR){
        listdir(current);
    }
    printf("%s\n", curr_ent->d_name);
    return;
}

我做错了什么?

一切正常,您只是忘记了豁免 ...。这两个 "virtual" 目录存在于所有目录中。 .是"self"的快捷方式,..parent的快捷方式。

例如如果你做了 listdir('.'),那么你会继续循环,因为你在 . 中做 opendir 的第一件事是另一个 .,它指向完全相同的地方。

简而言之,您需要以下伪代码:

if (dir != '.' && dir != '..' && is_dir(dir)) {
    listdir(dir);
}

What am I doing wrong?

  1. 您还没有添加代码来忽略 ...
  2. 您在递归调用中使用了相同的 DIR*

下面是我将如何更改您的功能。

int is_dot_or_dot_dot(char const* name)
{
   return (strcmp(name, ".") == 0 || strcmp(name, "..") == 0 );
}

void listdir(char const* dirname)
{
   char* subdir;
   DIR* dirp = opendir(dirname);
   struct dirent *curr_ent;

   if ( dirp == NULL )
   {
      return;
   }

   while ( (curr_ent = readdir(dirp)) != NULL )
   { 
      // Print the name.
      printf("%s\n", curr_ent->d_name);

      // Traverse sub-directories excluding . and ..
      // Ignore . and ..
      if ( curr_ent->d_type == DT_DIR && ! (is_dot_or_dot_dot(curr_ent->d_name)) )
      {
         // Allocate memory for the subdirectory.
         // 1 additional for the '/' and the second additional for '[=10=]'.
         subdir = malloc(strlen(dirname) + strlen(curr_ent->d_name) + 2);

         // Flesh out the subdirectory name.
         strcpy(subdir, dirname);
         strcat(subdir, "/");
         strcat(subdir, curr_ent->d_name);

         // List the contents of the subdirectory.
         listdir(subdir);

         // Free the allocated memory.
         free(subdir);
      }
   }

   // Close the directory
   closedir(dirp);
}