在C++17标准中,std::filesystem库为文件系统操作提供了统一的接口。下面展示了一个完整的示例,演示如何利用 std::filesystem::recursive_directory_iterator 对指定目录进行递归遍历,并打印出所有文件与子目录的路径、大小以及最后修改时间。示例代码可直接复制到任何支持C++17的编译器中运行。
#include <iostream>
#include <iomanip>
#include <filesystem>
#include <chrono>
#include <sstream>
namespace fs = std::filesystem;
// 将std::filesystem::file_time_type转换为可读的字符串
std::string format_time(const fs::file_time_type& ftime) {
auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(
ftime - fs::file_time_type::clock::now()
+ std::chrono::system_clock::now());
std::time_t tt = std::chrono::system_clock::to_time_t(sctp);
std::tm tm = *std::localtime(&tt);
std::ostringstream oss;
oss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");
return oss.str();
}
void print_directory(const fs::path& root) {
if (!fs::exists(root) || !fs::is_directory(root)) {
std::cerr << "错误: 目录不存在或不是目录。\n";
return;
}
std::cout << "递归遍历目录: " << fs::absolute(root) << '\n';
std::cout << std::left << std::setw(40) << "路径" << std::setw(12) << "大小 (字节)" << std::setw(20) << "最后修改时间" << '\n';
std::cout << std::string(72, '-') << '\n';
for (const auto& entry : fs::recursive_directory_iterator(root)) {
try {
std::string path = fs::absolute(entry.path()).string();
std::uintmax_t size = 0;
if (fs::is_regular_file(entry.status())) {
size = fs::file_size(entry);
}
std::string mtime = format_time(fs::last_write_time(entry));
std::cout << std::left << std::setw(40) << path << std::setw(12) << size << std::setw(20) << mtime << '\n';
} catch (const fs::filesystem_error& e) {
std::cerr << "访问文件时出错: " << e.what() << '\n';
}
}
}
int main(int argc, char* argv[]) {
fs::path dir = ".";
if (argc > 1) {
dir = argv[1];
}
print_directory(dir);
return 0;
}
代码说明
-
命名空间别名
namespace fs = std::filesystem;简化后续使用。
-
时间格式化
format_time函数将file_time_type转换为std::time_t,再用std::put_time生成易读字符串。此处做了时钟转换以兼容不同实现。 -
递归遍历
for (const auto& entry : fs::recursive_directory_iterator(root)) { … }recursive_directory_iterator自动深入子目录。若你想控制深度或排除某些路径,可使用fs::directory_options::skip_permission_denied或自行过滤。 -
错误处理
访问文件属性可能抛出filesystem_error,使用try-catch捕获并打印。 -
主函数
允许通过命令行参数指定根目录;若未提供,默认当前目录。
运行示例
$ g++ -std=c++17 -o dirwalk dirwalk.cpp
$ ./dirwalk /path/to/your/project
程序会输出类似以下内容:
递归遍历目录: /path/to/your/project
路径 大小 (字节) 最后修改时间
--------------------------------------------------------------------
/path/to/your/project/main.cpp 2156 2024-01-15 10:12:03
/path/to/your/project/include/util.h 342 2024-01-15 09:58:17
/path/to/your/project/src/utils.cpp 987 2024-01-15 10:00:45
...
进阶使用
- 过滤文件:在循环内判断
entry.path().extension()或使用正则表达式过滤。 - 并发遍历:将
recursive_directory_iterator与线程池结合,提升大目录的遍历性能。 - 属性统计:收集文件数、总大小、平均文件大小等统计信息。
以上示例展示了 std::filesystem 在递归遍历目录时的简洁性与强大功能。通过少量代码即可完成完整的文件系统扫描任务,为日志分析、备份工具、资源监测等场景提供便利。