温馨提示×

linux readdir为何返回空值

小樊
35
2026-10-17 07:32:28
栏目: 智能运维

在 Linux 下,readdir 返回 NULL 并不一定表示“目录为空”,而是有多种可能。下面按常见原因 + 排查方法来说明。


一、readdir 返回 NULL 的两种含义

struct dirent *readdir(DIR *dirp);
  • 返回非 NULL:读取到目录项
  • 返回 NULL:
    • 已读到目录末尾
    • 发生错误

⚠️ 无法仅靠返回值区分这两种情况


二、最常见原因

1️⃣ 已经读到目录结尾(正常情况)

这是最常见、也是“正确”的 NULL。

while ((entry = readdir(dir)) != NULL) {
    // 正常处理
}
// 最后一定会返回 NULL

✅ 目录本身可能是空的,也可能是读完了。


2️⃣ opendir 失败,但你仍在用 NULL 目录

DIR *dir = opendir("/some/path");
// 没检查 dir == NULL
readdir(dir); // 未定义行为 / 可能立刻返回 NULL

✅ 正确做法:

DIR *dir = opendir(path);
if (!dir) {
    perror("opendir");
    return -1;
}

3️⃣ 路径不存在 / 权限不足

  • 路径错误
  • 没有读权限(r + x)
ls -ld /some/dir

权限不足时 opendir 会失败。


4️⃣ 目录是空的

ls -a /path

若只有 . 和 ..,readdir 会直接返回 NULL。


5️⃣ 在循环中提前 break / continue 导致误判

while ((entry = readdir(dir)) != NULL) {
    if (strcmp(entry->d_name, "skip") == 0)
        break; // 你以为是空,其实只是 break
}

6️⃣ 多线程 / 目录被并发修改

  • 另一个进程删除文件
  • NFS / 网络文件系统异常

三、如何判断是“结束”还是“错误”

errno = 0;
struct dirent *entry = readdir(dir);

if (entry == NULL) {
    if (errno != 0) {
        perror("readdir");
    } else {
        printf("目录读取结束\n");
    }
}

四、一个健壮的示例代码

#include <dirent.h>
#include <stdio.h>
#include <errno.h>

int main() {
    DIR *dir = opendir(".");
    if (!dir) {
        perror("opendir");
        return 1;
    }

    errno = 0;
    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        printf("%s\n", entry->d_name);
    }

    if (errno != 0) {
        perror("readdir");
    }

    closedir(dir);
    return 0;
}

五、快速排查清单 ✅

  • [ ] opendir 是否成功?
  • [ ] 目录是否存在?
  • [ ] 是否有读权限?
  • [ ] 目录是否为空?
  • [ ] 是否读到结尾?
  • [ ] 是否检查 errno?

如果你愿意,可以把你的代码片段 + 目录情况贴出来,我可以直接帮你定位是哪一种原因。

0 踩