在C++17之后,标准库提供了头文件,它让文件系统操作变得轻而易举。下面我们将演示如何利用std::filesystem的递归遍历功能,列举指定目录下的所有文件与子目录,并对每个文件输出其大小、类型以及最后修改时间。
#include <iostream>
#include <iomanip>
#include <filesystem>
#include <chrono>
#include <ctime>
namespace fs = std::filesystem;
// 将std::chrono::file_clock时间转换为可读字符串
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 cftime = std::chrono::system_clock::to_time_t(sctp);
std::tm tm = *std::localtime(&cftime);
char buf[100];
std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
return std::string(buf);
}
int main()
{
std::string path;
std::cout << "请输入要遍历的目录路径: ";
std::getline(std::cin, path);
if (!fs::exists(path)) {
std::cerr << "路径不存在!\n";
return 1;
}
std::cout << "\n--- 目录内容列表 ---\n";
std::cout << std::left << std::setw(40) << "路径" << std::setw(15) << "类型" << std::setw(10) << "大小(B)" << "修改时间" << '\n';
std::cout << std::string(90, '-') << '\n';
for (const auto& entry : fs::recursive_directory_iterator(path))
{
std::string type;
if (entry.is_regular_file()) type = "文件";
else if (entry.is_directory()) type = "目录";
else if (entry.is_symlink()) type = "符号链接";
else type = "其它";
uintmax_t size = entry.is_regular_file() ? entry.file_size() : 0;
std::string mtime = format_time(entry.last_write_time());
std::cout << std::left << std::setw(40) << entry.path().string() << std::setw(15) << type << std::setw(10) << size << mtime << '\n';
}
return 0;
}
代码要点解析
-
命名空间别名
namespace fs = std::filesystem;使后续代码更简洁。 -
递归遍历
fs::recursive_directory_iterator自动递归访问所有子目录。若想只列出顶层目录,使用fs::directory_iterator即可。 -
文件类型判断
entry.is_regular_file(),entry.is_directory(),entry.is_symlink()等成员函数可判断不同的文件系统对象类型。 -
文件大小
只有常规文件(不是目录或符号链接)才有file_size()。对于目录,我们通常把大小设为0。 -
时间格式化
C++17 的file_time_type与std::chrono::system_clock不兼容,必须先进行时钟转换。示例函数format_time把时间转换为易读的字符串。 -
异常处理
这里没有显式捕获异常,recursive_directory_iterator在遇到无权限文件时会抛出std::filesystem::filesystem_error。在生产代码中建议使用try-catch或error_code参数来避免程序崩溃。
运行示例
$ ./fs_list
请输入要遍历的目录路径: /usr/include
--- 目录内容列表 ---
路径 类型 大小(B) 修改时间
------------------------------------------------------------------------------------------
/usr/include/c++/12.2.1/iostream 文件 1024 2025-04-10 09:13:57
/usr/include/c++/12.2.1/iostream.h 文件 2048 2025-04-10 09:13:57
/usr/include/c++/12.2.1/bits/ios_base.h 文件 3072 2025-04-10 09:13:57
...
小结
通过 `
`,C++ 让文件系统操作变得异常方便。递归遍历只需一行迭代器声明,且代码可读性极高。掌握这些基本技巧后,你就能在自己的项目中灵活处理文件读取、目录扫描、权限判断等任务。祝你编码愉快!