在 Debian / Linux(glibc) 中,readdir 和 scandir 都是用来读取目录内容的函数,但它们在功能、使用方式和灵活性上有明显区别。
一、函数来源与头文件
| 函数 | 头文件 | 标准 |
|---|---|---|
readdir |
|
POSIX |
scandir |
|
GNU / BSD 扩展(非 POSIX) |
二、readdir 简介
函数原型
#include
DIR *opendir(const char *name);
struct dirent *readdir(DIR *dirp);
int closedir(DIR *dirp);
使用方式
DIR *dir = opendir(".");
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
printf("%s\n", entry->d_name);
}
closedir(dir);
特点
✅ 优点
- POSIX 标准,可移植性好
- 适合流式读取(目录很大时内存占用小)
❌ 缺点
- 只能顺序读取
- 不能直接排序
- 不能一次性拿到所有结果
- 需要手动过滤(如
.和..)
三、scandir 简介
函数原型
#include
int scandir(const char *dirp,
struct dirent ***namelist,
int (*filter)(const struct dirent *),
int (*compar)(const struct dirent **,
const struct dirent **));
使用方式
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);
特点
✅ 优点
- 一次性返回所有目录项
- 支持 过滤函数
- 支持 排序(alphasort / versionsort)
- 使用更方便
❌ 缺点
- 非 POSIX(GNU / BSD)
- 内存占用较大(目录很大时)
- 需要手动
free
四、核心区别对比
| 对比项 | readdir | scandir |
|---|---|---|
| 标准 | POSIX ✅ | 非 POSIX ❌ |
| 读取方式 | 流式 | 一次性 |
| 是否排序 | 否 | 支持 |
| 是否过滤 | 手动 | 支持 filter |
| 内存占用 | 小 | 大 |
| 使用复杂度 | 稍高 | 更低 |
| 适合大目录 | ✅ | ❌ |
五、性能与适用场景
✅ 使用 readdir
- 目录可能非常大
- 需要逐条处理
- 追求可移植性(POSIX)
✅ 使用 scandir
- 目录较小
- 需要排序(如
ls行为) - 需要过滤(如只列出
.conf文件) - 想减少代码量
六、Debian / glibc 注意事项
- Debian 使用的是 glibc
scandir在 glibc 中属于 GNU 扩展- 编译时一般不需要额外参数
- 若追求严格 POSIX,应避免
scandir
七、总结一句话
readdir 适合“流式、底层、可移植”读取目录;
scandir 适合“简单、完整、可排序过滤”的一次性读取。
如果你愿意,我可以给你一个 readdir vs scandir 的完整示例对比,或者讲讲它们在 内核 / VFS 层面的差异。
