std::filesystem::recursive_directory_iterator是c++17起标准跨平台遍历方案,需检查is_regular_file()、捕获filesystem_error,并注意符号链接与硬链接处理。

用 std::filesystem::recursive_directory_iterator 遍历并累加文件大小
直接上手:C++17 起,std::filesystem 是唯一标准、跨平台的方案。别碰 Boost 或自己写递归遍历,容易漏符号链接、权限错误或路径越界。
关键点是:迭代器默认会跳过无法访问的条目(比如无权限子目录),但不会报错——你得主动检查 status(),否则统计结果偏小却毫无提示。
- 每次迭代必须调用
is_regular_file()过滤掉目录、socket、设备文件等非普通文件 - 对每个普通文件,用
file_size(entry)获取大小;若抛出std::filesystem::filesystem_error(如权限不足、文件被删除中),需捕获并跳过 - 注意:
file_size()对空文件返回 0,合法;但对符号链接,默认返回链接目标大小(不是链接本身),如需链接自身大小,得用symlink_status().size()
uintmax_t total = 0;
for (const auto& entry : std::filesystem::recursive_directory_iterator(path)) {
try {
if (std::filesystem::is_regular_file(entry.status())) {
total += std::filesystem::file_size(entry);
}
} catch (const std::filesystem::filesystem_error&) {
// 忽略无法读取的文件,不中断遍历
continue;
}
}
为什么不用 std::filesystem::directory_iterator 手动递归
手动递归看似可控,实则埋雷:Windows 下长路径(>260 字符)、Linux 下循环符号链接、某些文件系统(如 NFS)返回 stale handle——这些都会让 directory_iterator 构造失败并抛异常,而 recursive_directory_iterator 内部已做容错处理,能跳过坏节点继续。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
recursive_directory_iterator支持options::skip_permission_denied构造参数,自动忽略权限错误,省去 try/catch - 手动递归需维护栈/队列,易写错边界(比如重复进入同一目录),而标准迭代器保证每个路径只访问一次
- 性能上无差别:两者底层都调用 OS 原生 API,
recursive_版本只是封装了递归逻辑,并非额外遍历
常见错误:统计结果比 du -sb 小很多
这几乎一定是没处理硬链接或符号链接导致的——同一个 inode 被多次计数,或链接目标不可达被跳过。
- 硬链接:
file_size()对所有硬链接返回相同值,这是正确行为;但若你希望“去重统计”,得自己缓存std::filesystem::hard_link_count()和std::filesystem::inode()(POSIX)或GetFileInformationByHandle()(Windows),标准库不提供跨平台 inode 去重 - 符号链接:默认跟随,若目标不存在,
file_size()抛异常;加std::filesystem::symlink_status()可查链接本身是否有效 - 稀疏文件:
file_size()返回逻辑大小(含空洞),和du的实际磁盘占用不同,这是设计使然,不是 bug
Windows 下路径长度超限或中文乱码问题
即使开了 long path support,std::filesystem 在 Windows 上仍可能因编码或 UNC 路径格式失败。
- 确保传入的是 UTF-8 编码的
std::string(而非std::wstring),MSVC 和 Clang 都支持;GCC 旧版本需编译时加-finput-charset=UTF-8 - 路径开头加
\\?\前缀可绕过 MAX_PATH 限制,但std::filesystem不自动加——你得手动拼接:std::filesystem::path(L"\\?\") / your_path - 避免用
std::cout 调试中文路径,Windows 控制台默认 GBK;改用 <code>wcout 或日志写入文件
catch,少猜十分钟。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










