在 Linux 下使用 readdir()(或 readdir_r())遍历目录时“丢文件”,通常不是内核真的丢了文件,而是用法或环境导致你没读到。常见原因如下:
最常见错误:
struct dirent *de = readdir(dir);
// 只读了一次
readdir() 每次只返回一个条目,必须循环:
struct dirent *de;
while ((de = readdir(dir)) != NULL) {
// 处理 de
}
否则只会看到第一个文件。
如果在 opendir() 之后:
可能导致:
这是 POSIX 明确规定的未定义/实现相关行为。
✅ 正确做法:
open() + getdents() 并自己处理struct dirent 中:
char d_name[256];
这只是 占位大小,并不保证足够。在某些实现中(尤其老 glibc),长文件名可能被截断。
✅ 更安全:
readdir_r()(仍有限制)getdents64()你可能在代码里写了:
if (de->d_name[0] == '.') continue;
这会丢掉:
...在 NFS / 网络文件系统 上:
本地 ext4 / xfs 一般不会丢。
readdir() 返回 NULL 可能是:
正确写法:
errno = 0;
while ((de = readdir(dir)) != NULL) {
...
}
if (errno != 0) {
perror("readdir");
}
如果你直接用:
getdents()buffer 太小会导致部分条目丢失。
DIR *dir = opendir(path);
if (!dir) { perror("opendir"); return; }
struct dirent *de;
errno = 0;
while ((de = readdir(dir)) != NULL) {
if (strcmp(de->d_name, ".") == 0 ||
strcmp(de->d_name, "..") == 0)
continue;
printf("%s\n", de->d_name);
}
if (errno != 0)
perror("readdir");
closedir(dir);
可以贴出:
readdir 代码我可以精确判断是哪一种“丢文件”。