在 Debian(以及其它 Linux 发行版)上,readdir 是 POSIX / glibc 提供的目录读取函数,常用于 C/C++ 程序中遍历目录。下面从基本概念、使用示例、常见错误、替代方案几个方面说明如何“正确使用”。
readdir 用于逐个读取目录中的条目(文件、子目录、符号链接等)。
相关头文件:
#include <dirent.h>
#include <sys/types.h>
核心函数:
DIR *opendir(const char *name);
struct dirent *readdir(DIR *dirp);
int closedir(DIR *dirp);
#include <stdio.h>
#include <dirent.h>
int main(void) {
DIR *dir = opendir(".");
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_example.c -o readdir_example
struct dirent {
ino_t d_ino; // inode 号
off_t d_off;
unsigned short d_reclen;
unsigned char d_type; // 文件类型(不一定支持)
char d_name[256];
};
DT_REG 普通文件DT_DIR 目录DT_LNK 符号链接⚠️ 注意:
d_type 在某些文件系统上不可靠(如部分网络文件系统),需要类型时建议用 stat()。
#include <sys/stat.h>
struct stat st;
char path[512];
snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
if (stat(path, &st) == 0) {
if (S_ISDIR(st.st_mode))
printf("目录: %s\n", entry->d_name);
}
. 和 ..if (strcmp(entry->d_name, ".") == 0 ||
strcmp(entry->d_name, "..") == 0)
continue;
void list_dir(const char *path) {
DIR *dir = opendir(path);
if (!dir) return;
struct dirent *e;
while ((e = readdir(dir))) {
if (!strcmp(e->d_name, ".") || !strcmp(e->d_name, ".."))
continue;
char full[1024];
snprintf(full, sizeof(full), "%s/%s", path, e->d_name);
printf("%s\n", full);
if (e->d_type == DT_DIR)
list_dir(full);
}
closedir(dir);
}
readdir 不是线程安全int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
⚠️ 但 readdir_r 在新 glibc 中已被标记为废弃,官方建议用 readdir + 加锁。
在 Debian 64 位系统上:
readdir 实际等价于 readdir64❌ 忘记 closedir → 文件描述符泄漏
❌ 假设 d_type 一定有效
❌ 多线程共享 DIR*
❌ 用 readdir 后直接修改 d_name
std::filesystemnftw()(遍历整个目录树)find(非编程场景)如果你有具体使用场景(例如:遍历大目录、过滤文件、递归删除、性能问题),可以告诉我,我可以给你更针对性的示例。