应使用std::filesystem::recursive_directory_iterator并显式过滤普通文件,捕获filesystem_error跳过异常路径,累加file_size()结果;directory_iterator仅遍历单层,无法统计嵌套文件。

std::filesystem::recursive_directory_iterator遍历目录时如何累加文件大小
直接用 std::filesystem::file_size() 获取单个文件大小没问题,但递归遍历时容易忽略符号链接、权限拒绝和异常路径。默认迭代器会进入子目录,也包含目录本身(is_regular_file() 必须显式过滤)。
- 必须对每个
entry调用entry.is_regular_file(),否则目录、socket、设备文件等也会被计入(file_size()对非普通文件可能抛std::filesystem::filesystem_error) - 建议捕获
std::filesystem::filesystem_error并跳过(比如权限不足的子目录),不要让整个统计中断 -
std::filesystem::file_size()返回std::uintmax_t,用uint64_t或std::filesystem::space()的单位(字节)累加即可,无需转换单位
为什么不能直接用std::filesystem::directory_iterator
std::filesystem::directory_iterator 只遍历当前目录一层,不递归子目录。如果目标是“目录下所有文件”(含嵌套),必须用 recursive_directory_iterator;否则漏掉深层文件,总大小严重偏低。
-
recursive_directory_iterator默认跳过循环符号链接(symlink loop),行为安全;如需手动控制,可用std::filesystem::directory_options::follow_directory_symlink - 若目录结构极深,递归迭代器可能栈开销略高,但一般场景无感;真有深度限制需求,才需改用手动 BFS 遍历
完整可运行的累加逻辑示例(含错误处理)
#include <filesystem>
#include <iostream>
uint64_t get_total_file_size(const std::filesystem::path& root) {
uint64_t total = 0;
for (auto iter = std::filesystem::recursive_directory_iterator(root);
iter != std::filesystem::recursive_directory_iterator{};
++iter) {
try {
if (iter->is_regular_file()) {
total += std::filesystem::file_size(iter->path());
}
} catch (const std::filesystem::filesystem_error& e) {
// 权限拒绝、路径不存在等,跳过不影响整体
continue;
}
}
return total;
}
// 使用:std::cout
<p>注意:<code>iter->path()</code> 是 <code>std::filesystem::path</code> 类型,不能直接传给 <code>file_size()</code> 的重载版本(有些编译器版本要求显式转换);上面写法在 C++17 及以上标准中是安全的。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img
src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a>
<p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<h3>Windows 下路径编码和长路径支持的坑</h3>
<p>Windows 默认路径长度限制为 260 字符,启用长路径支持前,<code>std::filesystem</code> 可能对超长路径抛 <code>filesystem_error</code>(错误码为 <code>win32 error 206</code>,即“文件名或扩展名太长”)。</p>
<ul>
<li>确保程序 manifest 中启用了 longPathAware(Visual Studio 项目属性 → 清单工具 → 输入和输出 → 启用长路径)</li>
<li>或在代码开头调用 <code>SetThreadErrorMode(SEM_FAILCRITICALERRORS, nullptr)</code>(仅 Windows),但这不是 <code>std::filesystem</code> 的标准补救方式</li>
<li>macOS/Linux 无此限制,但要注意挂载的 NFS 或 FUSE 文件系统可能返回不一致的 <code>file_size()</code>(如管道、特殊文件)</li>
</ul>
<p>真正麻烦的是硬链接重复计数——<code>std::filesystem::file_size()</code> 按 inode 计算,但 <code>recursive_directory_iterator</code> 不自动去重;如果目录树里有硬链接指向同一文件,会被多次累加。需要自己维护 <code>std::set<:pair ino_t>></:pair></code> 去重,这个细节多数人会忽略。</p></iostream></filesystem>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










