温馨提示×

如何在Linux使用readdir

小樊
37
2026-08-18 02:27:38
栏目: 智能运维

在 Linux 下使用 readdir 主要是用来遍历目录中的文件和子目录readdir 是 POSIX 标准 C 库函数,定义在 <dirent.h> 中,常用于 Linux/Unix 目录操作。

下面从基本概念 → 示例代码 → 常见用法与注意点系统说明。


一、readdir 基本概念

相关函数

#include <dirent.h>

DIR *opendir(const char *name);
struct dirent *readdir(DIR *dirp);
int closedir(DIR *dirp);

关键结构体

struct dirent {
    ino_t          d_ino;       // inode 号
    off_t          d_off;
    unsigned short d_reclen;
    unsigned char  d_type;      // 文件类型(部分系统支持)
    char           d_name[256]; // 文件名
};

二、最简单的 readdir 示例

示例:列出当前目录所有文件名

#include <stdio.h>
#include <dirent.h>

int main() {
    DIR *dir = opendir(".");
    if (dir == NULL) {
        perror("opendir");
        return 1;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        printf("%s\n", entry->d_name);
    }

    closedir(dir);
    return 0;
}

编译运行:

gcc readdir_example.c -o readdir_example
./readdir_example

三、过滤 ...

readdir 会返回 ...,通常需要过滤:

while ((entry = readdir(dir)) != NULL) {
    if (strcmp(entry->d_name, ".") == 0 ||
        strcmp(entry->d_name, "..") == 0)
        continue;

    printf("%s\n", entry->d_name);
}

四、判断文件类型(推荐方式)

方法 1:使用 d_type(不一定全支持)

if (entry->d_type == DT_REG) {
    printf("普通文件: %s\n", entry->d_name);
} else if (entry->d_type == DT_DIR) {
    printf("目录: %s\n", entry->d_name);
}

⚠️ 注意:某些文件系统(如 NFS)可能 d_type == DT_UNKNOWN


✅ 方法 2(最可靠):lstat / stat

#include <sys/stat.h>
#include <string.h>

struct stat st;
char path[512];

snprintf(path, sizeof(path), "./%s", entry->d_name);
lstat(path, &st);

if (S_ISREG(st.st_mode)) {
    printf("文件: %s\n", entry->d_name);
} else if (S_ISDIR(st.st_mode)) {
    printf("目录: %s\n", entry->d_name);
}

五、递归遍历目录(简易版)

void list_dir(const char *path) {
    DIR *dir = opendir(path);
    if (!dir) return;

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        if (strcmp(entry->d_name, ".") == 0 ||
            strcmp(entry->d_name, "..") == 0)
            continue;

        printf("%s/%s\n", path, entry->d_name);
    }
    closedir(dir);
}

六、常见错误与注意事项

1. readdir 不是线程安全的

  • readdir 使用静态缓冲区
  • 多线程请用:
readdir_r(dir, entry, &result);  // 已废弃

✅ 现代推荐:

  • 单线程使用 readdir
  • 多线程避免共享 DIR*

2. readdir 返回的是文件名,不是路径

需要自己拼接完整路径:

sprintf(path, "%s/%s", dirname, entry->d_name);

3. 目录打开失败

if (opendir(path) == NULL) {
    perror("opendir");
}

七、readdir vs scandir

函数 特点
readdir 流式读取,内存占用小
scandir 一次性返回数组,方便排序
int scandir(const char *dir, struct dirent ***namelist,
            int (*filter)(const struct dirent *),
            int (*compar)(const struct dirent **, const struct dirent **));

八、总结

readdir 使用流程:

opendir → readdir → 处理 d_name → closedir

✅ 适合:

  • 目录遍历
  • 文件扫描
  • 构建 ls 类似功能

如果你需要:

  • 递归遍历目录树
  • 实现 ls -l
  • 过滤特定类型文件
  • 结合 inotify / epoll

可以告诉我你的具体使用场景,我可以给你更贴近实战的代码。

0