c++中如何使用std::filesystem::recursive_directory_iterator_c++递归遍历目录【实例】

std::filesystem::recursive_directory_iterator默认跳过符号链接、深度优先遍历;需显式指定directory_options::follow_directory_symlink才跟随软链接;可用disable_recursion_pending()跳过指定子目录。

std::filesystem::recursive_directory_iterator 怎么用

直接构造就能开始遍历,它默认自动跳过符号链接(不跟随),且会按深度优先顺序进入子目录。关键点是:必须用 std::fi

lesystem::directory_options::follow_directory_symlink 才能跟随软链接;否则遇到 symlink 会跳过——这点容易被忽略,尤其在跨平台调试时。

基础写法:

for (auto it = std::filesystem::recursive_directory_iterator("/path"); it != std::filesystem::end(it); ++it) {
    std::cout << it->path() << "\n";
}

如何跳过特定子目录(比如 .git、build)

迭代器本身不提供过滤接口,得靠手动判断 it->path().filename()it->path().string(),再配合 it.disable_recursion_pending() 阻止进入当前项(仅对目录有效)。

常见做法:

  • 在循环体内检查 it->is_directory()
  • 若目录名匹配黑名单(如 "build"".git"),调用 it.disable_recursion_pending()
  • 注意:该调用只对当前迭代位置生效,必须在 ++it 前执行

示例片段:

for (auto it = std::filesystem::recursive_directory_iterator("/src"); it != std::filesystem::end(it); ++it) {
    if (it->is_directory()) {
        auto name = it->path().filename().string();
        if (name == ".git" || name == "build" || name == "__pycache__") {
            it.disable_recursion_pending();
            continue;
        }
    }
    std::cout << it->path() << "\n";
}

遍历时抛出 filesystem_error 怎么处理

权限不足、路径被删除、挂载点失效等都会触发 std::filesystem::filesystem_error 异常。默认情况下,迭代器遇到错误会直接 throw,导致遍历中断。

解决方式只有两种:

  • std::filesystem::directory_options::skip_permission_denied 选项构造迭代器,跳过无权访问的条目
  • 捕获异常并重置迭代器(不推荐,因标准未保证异常后迭代器状态可恢复)

安全写法:

try {
    for (auto it = std::filesystem::recursive_directory_iterator(
             "/home/user", std::filesystem::directory_options::skip_permission_denied);
         it != std::filesystem::end(it); ++it) {
        std::cout << it->path() << "\n";
    }
} catch (const std::filesystem::filesystem_error& e) {
    std::cerr << "FS error: " << e.what() << "\n";
}

Windows 下路径分隔符和长路径要注意什么

Windows 默认限制 MAX_PATH=260,而 std::filesystem 在启用 long path 支持的前提下才能处理超过该长度的路径。需要确认两点:

  • 编译时链接器设置:MSVC 需开启 /Zc:wchar_t 和 Unicode 支持
  • 系统级配置:Windows 10+ 要在组策略或注册表中启用 LongPathsEnabled
  • it->path() 返回的是 std::filesystem::path,其 c_str() 在 Windows 上返回 wchar_t*,不能直接传给 ANSI C 函数

跨平台安全输出建议用:

std::wcout << it->path() << L"\n"; // Windows
// 或转为 UTF-8 字符串(需 std::filesystem::path::u8string(),C++20 起)
递归遍历看似简单,但权限控制、符号链接行为、异常恢复、长路径兼容这四点,在真实项目里几乎每次都会踩到至少一个。尤其是 disable_recursion_pending() 的调用时机和 skip_permission_denied 的选项位置,错一个字符就可能漏掉整个子树或 crash。