c++如何使用std-filesystem遍历目录_c++文件管理【手册】

1次阅读

应捕获异常并使用skip_permission_denied选项:构造时传入std::Filesystem::directory_options::skip_permission_denied,循环内仍需try/catch处理windows系统路径等残留异常。

c++如何使用std-filesystem遍历目录_c++文件管理【手册】

std::filesystem::recursive_directory_iterator 怎么用才不崩溃

直接用 std::filesystem::recursive_directory_iterator 遍历目录,最常见崩溃原因是迭代器在目录被并发修改(如另一线程删文件)或权限突变时抛出未捕获异常。它默认不跳过错误项,一遇到 permission_deniednot_foundthrow std::filesystem::filesystem_error

实操建议:

立即学习C++免费学习笔记(深入)”;

  • 必须用 try/catch 包裹单次 ++it 或解引用操作,不能只包整个循环
  • 想跳过不可访问路径,改用带 std::filesystem::directory_options::skip_permission_denied构造函数
    for (auto it = std::filesystem::recursive_directory_iterator(path, std::filesystem::directory_options::skip_permission_denied); it != std::filesystem::recursive_directory_iterator(); ++it) { /* ... */ }
  • Windows 上对某些系统路径(如 C:$Recycle.Bin)即使加了 skip_permission_denied 仍可能触发异常,需额外 catch 并 continue

遍历中判断是文件还是目录的正确方式

别用 it->path().extension()字符串匹配来猜类型——这根本不可靠。真实类型由文件系统元数据决定,且符号链接需要显式解析。

实操建议:

立即学习C++免费学习笔记(深入)”;

  • it->is_regular_file()it->is_directory()it->is_symlink() 这类成员函数,它们基于 it->status() 缓存结果,高效且语义明确
  • 如果需要区分“符号链接指向目录”还是“普通目录”,得先调 it->symlink_status() 再判断,因为 it->status() 默认会跟随链接
  • 注意:it->path() 返回的是相对当前迭代深度的路径,不是绝对路径;要绝对路径就写 std::filesystem::absolute(it->path())

为什么 std::filesystem 在 macos 或旧 linux 上编译不过

不是代码写错了,是链接和标准库支持没到位。c++17 的 std::filesystem 在 GCC 8+、Clang 9+ 才有完整实现,但即使编译器支持,运行时仍依赖系统级支持。

实操建议:

立即学习C++免费学习笔记(深入)”;

  • GCC 下必须显式链接 -lstdc++fs,否则报 undefined reference 到 std::filesystem::u8path 等符号
  • macOS 10.15+ 自带完整支持;低于此版本需用 libc++ 并确保 xcode command line tools ≥ 11.4
  • Linux 上若用 musl(如 Alpine),std::filesystem 基本不可用,得换 boost::filesystem 或 syscall 封装

递归遍历性能差?别让 path() 字符串拼接拖慢你

每次调 it->path() 都可能触发一次路径字符串拼接,尤其深层嵌套目录下,it->path().filename()it->path().parent_path() 频繁调用会明显放大开销。

实操建议:

立即学习C++免费学习笔记(深入)”;

  • it->path() 结果存到局部 const auto& p = it->path();,后续所有操作复用这个引用
  • 避免在循环内反复调 p.extension() —— 它内部做字符串查找;如只需判断是否为 .log,直接用 p.filename().String().ends_with(".log")(C++20)或手写后缀比对更稳
  • 真要极致性能(比如扫描百万级小文件),考虑用平台原生 API(FindFirstFile / readdir),std::filesystem 本质是封装,没法绕过 stat 和路径解析成本

最容易被忽略的是:recursive_directory_iterator 构造时不检查 path 是否存在或可读,第一次 ++ 才真正打开目录。这意味着错误延迟暴露,日志里看到的异常位置往往不是问题源头。

text=ZqhQzanResources