在 Linux 下用 C 语言读取目录,通常使用 <dirent.h> 提供的 opendir / readdir / closedir 接口。下面从基本用法到完整示例给你讲清楚。
opendirDIR *opendir(const char *name);
打开一个目录,成功返回 DIR*,失败返回 NULL。
readdirstruct dirent *readdir(DIR *dirp);
读取目录项,每次调用返回一项:
struct dirent {
ino_t d_ino; // inode 号
off_t d_off;
unsigned short d_revents;
unsigned char d_type; // 文件类型
char d_name[256]; // 文件名
};
返回 NULL 表示读取结束或出错。
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 == 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_demo.c -o readdir_demo
./readdir_demo /tmp
d_type 常见值:
DT_REG:普通文件DT_DIR:目录DT_LNK:符号链接while ((entry = readdir(dir)) != NULL) {
if (entry->d_type == DT_DIR) {
printf("[DIR] %s\n", entry->d_name);
} else {
printf("[FILE] %s\n", entry->d_name);
}
}
. 和 ..if (strcmp(entry->d_name, ".") == 0 ||
strcmp(entry->d_name, "..") == 0)
continue;
#include <stdio.h>
#include <string.h>
#include <dirent.h>
void list_dir(const char *path) {
DIR *dir = opendir(path);
if (!dir) return;
struct dirent *entry;
char fullpath[1024];
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 ||
strcmp(entry->d_name, "..") == 0)
continue;
snprintf(fullpath, sizeof(fullpath), "%s/%s", path, entry->d_name);
printf("%s\n", fullpath);
if (entry->d_type == DT_DIR) {
list_dir(fullpath);
}
}
closedir(dir);
}
int main() {
list_dir(".");
return 0;
}
| 问题 | 原因 |
|---|---|
readdir 返回乱码 |
d_name 只在该次调用有效 |
忘记 closedir |
文件描述符泄漏 |
用 readdir 判断文件是否存在 |
❌ 不适合,用 stat |
readdir_r(线程安全,已不推荐)scandir(排序、过滤)fts_* / nftw(复杂遍历)如果你愿意,我可以:
ls -lreaddir 在内核层怎么工作你想看哪一个?