c++17如何遍历一个目录下的所有文件 filesystem库使用指南【系统编程】

C++17 的 库提供跨平台目录遍历能力,核心是 std::filesystem::directory_iterator(遍历一级子项)和 recursive_directory_iterator(递归遍历)。

C++17 的 库提供了跨平台的目录遍历能力,无需依赖 Boost 或系统 API,核心是 std::filesystem::directory_iteratorstd::filesystem::recursive_directory_iterator

基础遍历:当前目录下的直接子项

使用 directory_iterator 可以逐个访问指定路径下的一级文件和子目录(不递归):

示例代码:

#include 
#include 

namespace fs = std::filesystem;

int main() {
    for (const auto& entry : fs::directory_iterator("/path/to/dir")) {
        std::cout << entry.path().filename().string() << "\n";
        // entry.is_regular_file(), entry.is_directory() 等可判断类型
    }
}

注意:directory_iterator 不保证顺序,如需排序,可先收集到 std::vector 再调用 std::sort

递归遍历:所有子目录及其中文件

recursive_directory_iterator 自动深入每一层子目录:

  • 默认跳过符号链接指向的目标(即不跟随 symlink),如需跟随,构造时传入 fs::directory_options::follow_directory_symlink
  • 可用 pop() 跳出当前层级(例如过滤掉某子树),配合 depth() 判断当前深度
  • 遍历时可能抛出 fs::filesystem_error(如权限不足),建议用 try-catch 包裹

过滤与判断:只处理特定类型或名称的文件

遍历中常需筛选,推荐方式:

  • entry.is_regular_file() 排除非普通文件(如目录、socket、设备文件)
  • entry.path().extension() == ".txt" 检查扩展名(注意 extension() 返回 fs::path,比较时用 .string() 或直接 path 比较)
  • entry.path().filename().string() 获取纯文件名做字符串匹配
  • 避免用 entry.path().string().find(...) 做路径匹配——易受路径分隔符或编码影响,应使用 fs::path 的成员函数(如 has_filename, parent_path

错误处理与性能提醒

真实场景中必须考虑健壮性:

  • 构造迭代器前,先用 fs::exists(path) && fs::is_directory(path) 验证路径有效性
  • 循环内捕获 const fs::filesystem_error& e,检查 e.code().value() 区分 ENOENT、EACCES 等错误
  • 大量小文件时,recursive_directory_iterator 可能比 shell 命令慢,因每次 stat 系统调用开销;如仅需文件名,可考虑 fs::directory_entry::path() 而非立即调用 status()