在 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?
- 您还没有添加代码来忽略
.
和 ..
。
- 您在递归调用中使用了相同的
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);
}
我一直在尝试学习如何使用函数与系统上的路径交互,但我想我一开始就卡住了。
我特别搜索了 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?
- 您还没有添加代码来忽略
.
和..
。 - 您在递归调用中使用了相同的
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);
}