在 Linux 下,readdir 是用来遍历目录的标准 POSIX 接口,通常和 opendir / closedir 配合使用。下面从基本用法 → 示例 → 注意事项给你讲清楚。
#include <dirent.h>
#include <stdio.h>
DIR *dir = opendir(path); // 打开目录
if (!dir) { perror("opendir"); return; }
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
// 处理 entry->d_name
}
closedir(dir); // 关闭目录
opendirDIR *opendir(const char *name);
DIR*NULLreaddirstruct dirent *readdir(DIR *dirp);
NULL 表示结束或出错struct dirent {
ino_t d_ino;
off_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[256];
};
常用字段:
d_name:文件名d_type:文件类型(可选):
DT_REG 普通文件DT_DIR 目录DT_LNK 符号链接closedirint closedir(DIR *dirp);
#include <stdio.h>
#include <dirent.h>
int main(int argc, char *argv[]) {
const char *path = argc > 1 ? argv[1] : ".";
DIR *dir = opendir(path);
if (!dir) {
perror("opendir");
return 1;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
printf("%s\n", entry->d_name);
}
closedir(dir);
return 0;
}
编译运行:
gcc readdir_demo.c -o readdir_demo
./readdir_demo /tmp
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
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;
char full[1024];
snprintf(full, sizeof(full), "%s/%s", path, entry->d_name);
printf("%s\n", full);
if (entry->d_type == DT_DIR) {
list_dir(full);
}
}
closedir(dir);
}
int main() {
list_dir(".");
return 0;
}
⚠️ 注意:某些文件系统
d_type可能不可用,需用stat()判断类型
. 和 .. 会包含必须手动跳过,否则递归会死循环
readdir 不是线程安全的线程安全版本:
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
(已逐步废弃,推荐 readdir + 单线程或加锁)
d_name 是变长数组,不要越界拷贝
scandir 的区别(补充)如果你想排序 / 过滤:
scandir(path, &namelist, filter, alphasort);
更方便,但会一次性加载全部目录项。
如果你需要:
getdents 实现可以直接说,我给你对应示例。