std::filesystem::directory_iterator 默认非递归,遍历时遇权限拒绝会抛异常,需用 try/catch 或构造时指定 directory_options::skip_permission_denied 来跳过;路径须存在可读,推荐传 std::filesystem::path 对象并配合 status() 复用避免重复 stat。

用 std::filesystem::directory_iterator 遍历当前目录(不进子目录)
它默认就是非递归的——只要别手动调用 std::filesystem::recursive_directory_iterator,就不会往下钻。很多人误以为它会自动递归,其实是混淆了两个迭代器类型。
常见错误现象:directory_iterator 走着走着突然卡住或报 filesystem::filesystem_error: Permission denied,不是因为递归,而是遇到无读权限子目录时抛异常中断了遍历。
- 必须用
try/catch包裹单次++it或解引用,否则权限/符号链接失效等都会导致崩溃 - 若想跳过不可访问项继续遍历,得配合
std::filesystem::directory_options::skip_permission_denied -
directory_iterator构造时路径末尾加不加/没影响,但路径本身必须存在且可读
directory_iterator 构造时怎么传路径才安全
直接传 std::filesystem::path 对象最稳妥;传 C 字符串要小心隐式转换失败(比如含宽字符、空字节或非法 UTF-8)。
使用场景:遍历当前工作目录、某配置目录下的所有配置文件、插件目录下的 .so 文件——这些都不需要深入子级。
- 推荐写法:
for (const auto& entry : std::filesystem::directory_iterator("/etc")) - 避免裸 C 字符串:
directory_iterator("C:\temp")在 Windows 下因反斜杠转义出错,应写成R"(C:\temp)"或用正斜杠 - 构造后立即检查是否可遍历:
if (it == std::filesystem::directory_iterator{})表示目录为空或不可读(注意:这不抛异常)
为什么加了 skip_permission_denied 还是报错
因为这个选项只对构造时的目录本身生效,不控制后续迭代过程中的权限检查。真正起作用的是在构造函数里显式传入选项参数。
Agent 记忆系统 — 五路融合检索 + 双时间线 + 因果链 + Spirit管家 + 记忆回声 + 弹性配置 + Circuit Breaker + GDPR合规 + 192项安全审计修复
性能影响:启用该选项不会降低速度,只是把原本抛异常的地方改成跳过条目;但要注意,它不会跳过其他错误(如断开的符号链接,除非额外设 follow_symlinks(false))。
- 正确写法:
std::filesystem::directory_iterator(path, std::filesystem::directory_options::skip_permission_denied) - 错误写法:
std::filesystem::directory_iterator(path).options(std::filesystem::directory_options::skip_permission_denied)——options()是 const 成员函数,返回副本,无效 - 如果路径中包含损坏的符号链接,默认行为是抛异常;加
follow_symlinks(false)可避免,但需和skip_permission_denied一起用位或:directory_options::skip_permission_denied | directory_options::follow_symlinks
遍历时怎么区分文件、目录、符号链接
别依赖 entry.path().extension() 或字符串判断,要用 entry.is_regular_file()、entry.is_directory() 等成员函数——它们内部调用 status(),能正确处理符号链接目标类型。
容易踩的坑:连续调用多个 is_* 函数会多次 stat,影响性能;应先存一份 std::filesystem::file_status s = entry.status(),再用 is_regular_file(s) 等自由函数复用状态。
-
entry.is_directory()返回 true 表示它是个目录(不管是否可进入) -
entry.exists()判断路径是否存在(对悬空 symlink 返回 false) - 想跳过子目录?直接
if (!entry.is_directory()) { /* 处理文件 */ }
实际用起来最麻烦的不是语法,是权限异常的捕获粒度和符号链接的语义选择——这两个点不提前想清楚,代码上线后在容器或 CI 环境里大概率挂。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










