C++17起可用std::filesystem::directory_iterator遍历目录,需显式启用-std=c++17(Linux/macOS)或项目属性中开启(Windows VS),示例包含和并遍历当前目录。

用 std::filesystem::directory_iterator 遍历当前目录最简单
只要编译器支持 C++17(GCC 8+、Clang 7+、MSVC 2017 15.7+),开 -std=c++17 就能直接用,不用第三方库。注意不是所有系统默认启用——Linux/macOS 要显式加编译选项,Windows VS 默认可能关着,得在项目属性里开 C++17 标准。
最简示例:
#include#include int main() { for (const auto& entry : std::filesystem::directory_iterator(".")) { std::cout << entry.path().filename() << "\n"; } }
-
directory_iterator默认不递归,只扫一层 - 构造时传入的路径必须存在且可访问,否则抛
std::filesystem::filesystem_error - 迭代器遍历顺序不保证,别依赖字母序或创建时间
- 路径对象
entry.path()是完整绝对路径(除非你传的是相对路径,它也保持相对)
遍历子目录要手动递归或换 recursive_directory_iterator
directory_iterator 不进子文件夹;想深度遍历,要么自己写递归,要么直接用 std::filesystem::recursive_directory_iterator——它自带栈管理,比手写更稳。
递归版一行切换:
立即学习“C++免费学习笔记(深入)”;
for (const auto& entry : std::filesystem::recursive_directory_iterator(".")) { ... }
- 遇到权限不足的子目录(比如
/proc下某些条目),默认会跳过并继续,不中断整个遍历 - 如果想捕获这类错误,得传入
std::filesystem::directory_options::skip_permission_denied显式控制(其实是默认值,但显式写出来更清晰) - 递归迭代器内部维护状态,不能随意拷贝后长期持有旧副本——用完即弃,避免悬空引用
过滤文件类型和跳过隐藏项得自己判断
directory_iterator 不提供内置过滤,所有逻辑都得手动做。常见需求如“只取普通文件”“跳过以 . 开头的隐藏项”,靠 entry.is_regular_file() 和 entry.path().filename().string()[0] == '.' 判断即可。
注意点:
-
entry.status()可能抛异常(如符号链接指向不存在路径),建议改用entry.symlink_status()避免意外中断 - Windows 下隐藏属性(
FILE_ATTRIBUTE_HIDDEN)不会反映在 filename 前缀里,得调entry.status().permissions()或平台 API - Linux/macOS 的隐藏文件只是命名约定,没系统级权限位,
.git这类全靠字符串匹配
性能敏感场景慎用 directory_iterator 构造时的 stat 开销
每次构造 directory_iterator,底层会为每个目录项调一次 stat()(或等价系统调用),获取类型、大小、时间戳等元数据。如果你只需要文件名,这步纯属浪费。
- 只需文件名?用
std::filesystem::directory_entry::path().filename()即可,别调entry.file_size()或entry.last_write_time() - 大量小文件场景下,频繁 stat 会显著拖慢遍历速度,尤其 NFS 或远程挂载目录
- 真要极致性能,C++20 的
std::filesystem::weakly_canonical或原生系统 API(opendir/readdir)更可控,但失去跨平台性
真正麻烦的不是语法,是路径有效性检查、权限边界、符号链接循环、编码不一致这些 runtime 行为——它们不会报编译错误,但一跑就崩或漏文件。









