C语言 无法递归访问子文件夹



我正在尝试构建一个程序,该程序递归列出目录中的所有文件夹和文件及其文件大小。我仍在研究第一部分,因为该程序似乎只深入了一级子文件夹。

任何人都可以在这里发现问题吗?我被卡住了。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <strings.h>
#include <dirent.h>
#include <unistd.h>
void listdir(const char *name) {
    DIR *dir;
    struct dirent *entry;
    int file_size;
    if (!(dir = opendir(name)))
        return;
    if (!(entry = readdir(dir)))
        return;
    do {
        if (entry->d_type == DT_DIR) {
            char path[1024];
            if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
                continue;
            printf("./%sn", entry->d_name);
            listdir(entry->d_name);
        }
        else
            printf("./%sn", entry->d_name);
    } while (readdir(dir) != NULL);
    closedir(dir);
}
int main(void)
{
    listdir(".");
    return 0;
}

第一个问题是在 while 条件下,您放弃了 readdir 的返回值,它应该分配给 entry。

此外,当递归调用listdir时,您应该在路径之前加上父名称,否则它将始终从当前工作目录中搜索。试试这个版本:

void listdir(const char *name) {
    DIR *dir;
    struct dirent *entry;
    int file_size;
    if (!(dir = opendir(name)))
            return;
    while ((entry = readdir(dir)) != NULL) {   // <--- setting entry
            printf("%s/%sn", name, entry->d_name);
            if (entry->d_type == DT_DIR) {
                    char path[1024];
                    if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
                            continue;
                    sprintf(path, "%s/%s", name, entry->d_name);  // <--- update dir name properly by prepend the parent folder.
                    listdir(path);
            }
    }
    closedir(dir);
}
int main(void)
{
    listdir(".");
    return 0;
}

以下是对代码的最小修复。我冒昧地在这里使用了非标准asprintf;如果您不使用 glibc,则应改用 snprintf 或类似功能。

最值得注意的是,提供给listdir的路径必须是当前工作目录的完整相对路径;或者绝对路径。但是,entry->d_name 中的那个只是文件的基本名称。因此,它必须与传递到listdir的路径连接。我还更改了不适当的do...while在这里进入一个while循环。

#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <strings.h>
#include <dirent.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void listdir(const char *path) {
    DIR *dir;
    struct dirent *entry;
    if (!(dir = opendir(path)))
        return;
    while ((entry = readdir(dir))) {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
            continue;
        char *current;
        if (asprintf(&current, "%s/%s", path, entry->d_name) < 0) {
            // asprintf failed
            fprintf(stderr, "asprintf failed, exiting");
            goto exit;
        }
        puts(current);
        if (entry->d_type == DT_DIR) {
            listdir(current);
        }
        free(current);
    }
exit:
    closedir(dir);
}
int main(void)
{
    listdir(".");
}

最新更新