温馨提示×

linux readdir怎么替代

小樊
48
2026-10-08 13:23:41
栏目: 智能运维

在 Linux 下,readdir()(以及 opendir() / readdir_r())用于遍历目录。如果你想要替代 readdir,常见有以下几种方案,取决于你的需求(性能、可移植性、编程语言、并发安全等)。


一、用 getdents / getdents64 系统调用(更底层、更快)

readdir() 本质是对 getdents64 的封装。

优点

  • 更少系统调用
  • 更高性能
  • 可一次读取多个目录项

示例(C)

#include <unistd.h>
#include <fcntl.h>
#include <sys/syscall.h>
#include <linux/dirent.h>
#include <stdio.h>

#define BUF_SIZE 4096

int main() {
    int fd = open(".", O_RDONLY | O_DIRECTORY);
    char buf[BUF_SIZE];
    int n = syscall(SYS_getdents64, fd, buf, BUF_SIZE);

    struct linux_dirent64 *dir;
    for (int bpos = 0; bpos < n; bpos += dir->d_reclen) {
        dir = (struct linux_dirent64 *)(buf + bpos);
        printf("%s\n", dir->d_name);
    }
    close(fd);
}

⚠️ 注意:这是 Linux 特有,不可移植。


二、使用 scandir(简化遍历)

scandir() 内部用 readdir,但更方便。

示例

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

int main() {
    struct dirent **namelist;
    int n = scandir(".", &namelist, NULL, alphasort);

    for (int i = 0; i < n; i++) {
        printf("%s\n", namelist[i]->d_name);
        free(namelist[i]);
    }
    free(namelist);
}

✅ 优点:

  • 自动排序
  • 代码简单

❌ 缺点:

  • 一次性加载所有项(内存占用)

三、使用 fts(递归遍历推荐)

如果你的目标是递归遍历目录,用 fts 替代 readdir 更合适。

#include <fts.h>
#include <stdio.h>

int main() {
    char *paths[] = {".", NULL};
    FTS *fts = fts_open(paths, FTS_NOCHDIR, NULL);

    FTSENT *ent;
    while ((ent = fts_read(fts))) {
        if (ent->fts_info == FTS_F)
            printf("%s\n", ent->fts_path);
    }
    fts_close(fts);
}

✅ 适合:

  • 递归目录
  • 文件查找工具

四、使用 nftw(标准库,遍历树)

#include <ftw.h>
#include <stdio.h>

int cb(const char *path, const struct stat *st, int flag, struct FTW *ftw) {
    printf("%s\n", path);
    return 0;
}

int main() {
    nftw(".", cb, 10, FTW_PHYS);
}

✅ POSIX 标准
✅ 支持深度限制


五、非 C 语言替代方案

C++

#include <filesystem>
for (auto &p : std::filesystem::directory_iterator("."))
    std::cout << p.path() << "\n";

Python

import os
for name in os.listdir("."):
    print(name)

Rust

for entry in std::fs::read_dir(".").unwrap() {
    println!("{}", entry.unwrap().file_name().to_string_lossy());
}

六、为什么想替代 readdir?

原因 推荐方案
性能差 getdents64
线程不安全 readdir_r(已废弃) / scandir
递归复杂 fts / nftw
现代开发 C++ std::filesystem
跨平台 高级语言 API

如果你能说一下:

  • 使用的语言
  • 是否需要递归
  • 是否关心性能或线程安全

我可以给你最合适的替代方案。

0 踩