std::filesystem::directory_iterator仅支持单层目录遍历,不递归,需手动处理符号链接、权限错误等;递归遍历应使用recursive_directory_iterator,并可配置skip_permission_denied等选项应对常见异常。

std::filesystem::directory_iterator 是 C++17 起标准库中遍历目录最直接的方式,但默认只做**一层遍历**(不递归),且对符号链接、权限错误、路径不存在等场景需主动处理。
用 directory_iterator 遍历当前目录(非递归)
它按文件系统实际顺序返回每个 directory_entry,不保证排序。构造时若路径无效或无读取权限,会抛出 std::filesystem::filesystem_error。
常见写法:
#include#include namespace fs = std::filesystem; int main() { try { for (const auto& entry : fs::directory_iterator("path/to/dir")) { std::cout << entry.path() << "\n"; } } catch (const fs::filesystem_error& e) { std::cerr << "遍历失败: " << e.what() << "\n"; } }
- 必须启用 C++17 或更高标准(如
-std=c++17) -
entry.path()返回的是完整路径(含父目录),不是纯文件名 - 若只想获取文件名,用
entry.path().filename() - 不会跳过
.和..,它们会被正常列出
递归遍历:改用 recursive_directory_iterator
这是真正“遍历所有子目录下文件”的标准方案。它内部维护一个栈,自动下降进入子目录,也支持提前退出(disable_recursion_pending())。
立即学习“C++免费学习笔记(深入)”;
示例:只打印普通文件(跳过目录、符号链接等)
for (const auto& entry : fs::recursive_directory_iterator("top/dir")) {
if (entry.is_regular_file()) {
std::cout << entry.path() << "\n";
}
}
- 遇到权限不足的子目录时,默认会抛异常;可传入
fs::directory_options::skip_permission_denied忽略 - 递归深度无硬限制,但过深可能引发栈或内存问题
- 若中途想跳过某个子目录(比如
build/),在迭代到该目录 entry 时调用iter.disable_recursion_pending()
常见报错和绕过方式
典型错误信息:filesystem error: cannot iterate directory: Permission denied 或 No such file or directory。
- 路径不存在 → 先用
fs::exists(path)和fs::is_directory(path)校验 - 权限被拒 → 构造
recursive_directory_iterator时加选项:fs::recursive_directory_iterator(path, fs::directory_options::skip_permission_denied) - Windows 下长路径(>260 字符)→ 确保路径以
\\?\开头,且编译器支持(MSVC 默认支持,GCC/Clang 需注意运行时) - 符号链接指向循环目录 →
recursive_directory_iterator默认会检测并抛filesystem_error,无法自动解环
性能与替代选择
directory_iterator 是轻量封装,底层调用系统 API(如 Linux 的 opendir/readdir),开销很小。但若只需文件名列表且不关心类型,手动用 readdir 可能略快(失去跨平台性)。
- 大量小文件时,频繁调用
entry.status()(如判断是否为文件)会触发额外系统调用;可改用entry.symlink_status()避免跟随链接 - 不需要实时遍历?考虑先用
fs::directory_iterator收集所有路径到vector,再离线处理,减少迭代器生命周期内的系统交互 - Windows 上若需通配符(如
*.cpp),filesystem不支持过滤,得自己用entry.path().extension() == ".cpp"判断
真正麻烦的不是怎么写循环,而是决定要不要递归、如何应对权限中断、以及是否要处理符号链接循环 —— 这些逻辑一旦漏掉,程序在某些目录下就直接 crash 或静默跳过。









