最常用、最轻量的遍历方式是用 std::filesystem::directory_iterator 遍历当前目录下的一级文件(不含子目录),需启用 c++17 并注意捕获 filesystem_error 异常。

用 std::filesystem::directory_iterator 遍历当前目录下的文件(不含子目录)
这是最常用、最轻量的遍历方式,适合只处理一级文件列表的场景。它不会递归进入子目录,性能开销小,且能直接获取每个 std::filesystem::path 对象。
注意:必须在编译时启用 C++17(如 -std=c++17),并链接 -lstdc++fs(GCC 早期版本需要,GCC 11+ 和 Clang 通常自动处理)。
常见错误是忽略异常——路径不存在或权限不足时会抛出 std::filesystem::filesystem_error,建议用 try/catch 包裹:
try {
for (const auto& entry : std::filesystem::directory_iterator(".")) {
if (entry.is_regular_file()) {
std::cout << entry.path().filename() << "\n";
}
}
} catch (const std::filesystem::filesystem_error& e) {
std::cerr << "遍历失败: " << e.what() << "\n";
}
- 只迭代当前目录,不进子目录
-
entry.path()返回完整路径;.filename()取文件名,.stem()取无扩展名部分,.extension()取扩展名 - 用
entry.status().type()或更简洁的is_*成员函数判断类型(如is_directory()、is_symlink())
用 std::filesystem::recursive_directory_iterator 深度遍历所有子目录
当需要“查找整个目录树下所有 .cpp 文件”这类需求时,必须用这个迭代器。它按深度优先顺序遍历,行为类似 shell 的 find . -type f。
立即学习“C++免费学习笔记(深入)”;
关键细节:默认会跳过符号链接指向的目标(即不跟随 symlink),但若传入 std::filesystem::directory_options::follow_directory_symlink,则可能引发循环遍历(比如软链接指向父目录)。生产环境慎用该选项。
for (const auto& entry : std::filesystem::recursive_directory_iterator("src")) {
if (entry.is_regular_file() && entry.path().extension() == ".cpp") {
std::cout << entry.path() << "\n";
}
}
- 构造时若路径不存在或不可读,同样抛出
filesystem_error - 可用
pop()方法临时跳过某个子目录(例如跳过build/):在循环中检测到目标路径后调用iter.pop() - 迭代器本身支持前向移动,但不支持随机访问或重置,需重新构造
如何安全过滤文件名、扩展名和访问权限
不能只靠字符串匹配扩展名(比如 path.string().find(".txt") != std::string::npos),因为 .txt.swp 也会被误判。应使用 path.extension(),它按最后的点分割,返回 ".txt" 这样的 path 对象,可直接比较。
权限检查容易被忽略:即使路径存在且是 regular file,也可能因权限不足导致 status() 失败。此时 entry.symlink_status() 更安全——它只查符号链接本身的元信息,不 dereference,几乎总能成功。
- 正确判断扩展名:
entry.path().extension() == ".log"(注意带点) - 区分
status()(获取目标文件状态)和symlink_status()(仅查链接自身) - 用
std::filesystem::exists(entry)前先确保没抛异常,否则应捕获再处理 - Windows 下路径大小写不敏感,Linux/macOS 敏感,过滤逻辑要考虑平台一致性
跨平台路径拼接与相对路径陷阱
别用 "/" + filename 拼路径——Windows 用反斜杠,而且双反斜杠或混合斜杠会导致 path 解析异常。一律用 / 操作符:
auto base = std::filesystem::path("data");
auto full = base / "config.json"; // 自动适配分隔符
相对路径(如 "../logs")在 directory_iterator 中会被正常解析,但要注意:如果当前工作目录变化,或传入的是相对路径而非绝对路径,entry.path() 返回的仍是相对形式。调试时建议先用 std::filesystem::absolute(entry.path()) 看真实位置。
-
path / "sub" / "file.txt"是推荐拼接方式,不是字符串拼接 -
path.parent_path()获取上层目录,path.has_extension()判是否有扩展名 - 避免把用户输入的路径直接传给迭代器——先用
std::filesystem::weakly_canonical()规范化(处理./、../、重复斜杠)
exists() 或 is_directory() 校验就直接迭代,程序就崩在用户机器上——而这种错误在你的开发机上很可能根本复现不了。











