C++ 怎么遍历文件夹 C++ filesystem directory_iterator用法【系统】

12次阅读

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

C++ 怎么遍历文件夹 C++ filesystem directory_iterator用法【系统】

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 行为——它们不会报编译错误,但一跑就崩或漏文件。

text=ZqhQzanResources