在现代 C++ 开发中,文件系统操作常常需要遍历目录树。自 C++17 起,标准库提供了 <filesystem> 头文件,方便进行文件路径操作、文件属性查询以及目录遍历。本文将展示一个完整示例,演示如何使用 std::filesystem::recursive_directory_iterator 在指定路径下递归搜索所有文件,并输出文件路径、大小以及修改时间。
1. 环境准备
- 编译器:支持 C++17 或更高版本,例如 g++-11、clang++-12 或 MSVC 2019(/std:c++17)
- 依赖:无外部库,直接使用标准库
g++ -std=c++17 -Wall -Wextra -O2 recursive_search.cpp -o recursive_search
2. 代码实现
#include <iostream>
#include <filesystem>
#include <chrono>
#include <iomanip>
namespace fs = std::filesystem;
// 格式化时间戳为易读字符串
std::string format_time(fs::file_time_type ft) {
using namespace std::chrono;
auto sctp = time_point_cast<system_clock::duration>(ft - fs::file_time_type::clock::now()
+ system_clock::now());
std::time_t t = system_clock::to_time_t(sctp);
std::tm tm = *std::localtime(&t);
std::ostringstream oss;
oss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");
return oss.str();
}
// 递归搜索函数
void recursive_search(const fs::path& dir) {
if (!fs::exists(dir)) {
std::cerr << "路径不存在: " << dir << '\n';
return;
}
if (!fs::is_directory(dir)) {
std::cerr << "指定路径不是目录: " << dir << '\n';
return;
}
for (const auto& entry : fs::recursive_directory_iterator(dir)) {
try {
if (entry.is_regular_file()) {
auto fsize = entry.file_size();
auto ftime = entry.last_write_time();
std::cout << "文件: " << entry.path() << '\n' << " 大小: " << fsize << " 字节\n" << " 最后修改: " << format_time(ftime) << '\n';
}
} catch (const std::exception& e) {
std::cerr << "访问文件失败: " << entry.path() << " -> " << e.what() << '\n';
}
}
}
int main(int argc, char* argv[]) {
if (argc < 2) {
std::cerr << "用法: " << argv[0] << " <目录路径>\n";
return 1;
}
fs::path target_dir(argv[1]);
recursive_search(target_dir);
return 0;
}
3. 关键点说明
| 关键点 | 说明 |
|---|---|
std::filesystem::recursive_directory_iterator |
自动递归遍历目录,轻松获取子目录和文件 |
entry.is_regular_file() |
过滤掉符号链接、目录等非普通文件 |
entry.file_size() |
读取文件大小,若文件被删除或无权限会抛异常 |
entry.last_write_time() |
获取文件最后修改时间,结合 format_time 转为可读字符串 |
| 异常处理 | 遍历过程中可能出现权限错误或删除操作,使用 try-catch 保证程序不崩溃 |
4. 扩展功能
- 按文件后缀筛选
if (entry.path().extension() == ".cpp") { /* 只处理 C++ 源文件 */ } - 并行遍历
使用std::async或第三方并发库(如 TBB)将每个子目录分配给线程,提高大目录下的扫描速度。 - 过滤隐藏文件
判断entry.path().filename().string().front() != '.'可跳过隐藏文件(Linux / macOS)或带点前缀的文件。 - 统计信息
在遍历过程中累加文件数量、总大小等,最后输出统计报告。
5. 小结
- C++17 ` ` 让文件系统操作变得直观且类型安全。
recursive_directory_iterator是实现递归搜索的核心工具。- 通过异常捕获与条件过滤,可以构建健壮且功能丰富的文件搜索工具。
随时将上述示例集成到你的项目中,即可快速获得跨平台的递归文件遍历功能。祝编码愉快!