c++oding="utf-8" ?>
最可靠方案是c++17起使用std::filesystem::recursive_directory_iterator递归遍历,检查is_regular_file()后累加file_size(),并捕获filesystem_error异常或使用error_code避免崩溃,同时注意硬链接去重和符号链接处理。

用 std::filesystem 递归遍历目录求和最可靠
标准库从 C++17 开始提供 std::filesystem,它是跨平台获取文件夹大小的首选方案。Windows、Linux、macOS 均支持,无需第三方依赖,且能正确处理符号链接、权限拒绝等边界情况。
关键点:必须启用递归遍历,因为 std::filesystem::file_size() 对目录本身只返回实现定义值(通常无意义),真正大小来自所有文件之和。
- 需在编译时开启 C++17 或更高标准(如
-std=c++17) - 路径要用
std::filesystem::path构造,避免裸字符串引发编码或转义问题 - 对每个
directory_entry先检查is_regular_file(),跳过目录、socket、设备文件等非数据项 - 捕获
std::filesystem::filesystem_error异常——比如权限不足时访问子目录会抛出,不处理会导致程序崩溃
uintmax_t get_directory_size(const std::filesystem::path& p) {
uintmax_t total = 0;
std::error_code ec;
for (const auto& entry : std::filesystem::recursive_directory_iterator(p, ec)) {
if (ec) continue; // 跳过无法访问的条目(如权限拒绝)
if (entry.is_regular_file()) {
total += entry.file_size(ec); // 同样容忍单个文件 size 获取失败
}
}
return total;
}
Windows 下用 GetDiskFreeSpaceEx 不适用
这个 API 返回的是驱动器剩余/总空间,不是某个文件夹占用的实际字节数。有人误以为它能算目录大小,结果发现数值完全对不上——它根本不读取目录结构,只查卷级元数据。
常见错误现象:GetDiskFreeSpaceEx 返回值与磁盘属性里“已用空间”一致,但和手动累加文件大小差几 GB。这是因为 NTFS 的压缩、稀疏文件、硬链接、回收站残留等机制导致“逻辑大小”和“物理占用”不等价。
- 别试图用它减法推导文件夹大小(例如“总空间 - 剩余空间”再扣其他目录),不可靠
- 若真要快速估算,
du /s(Windows PowerShell)或du -sb(WSL)更接近真实值,但仍是外部命令,非 C++ 原生方案
忽略符号链接和硬链接会导致重复计数
默认递归遍历会把每个硬链接都当作独立文件累加,造成结果虚高;符号链接若指向目录,还可能陷入无限循环(如软链 A → B,B → A)。
std::filesystem::recursive_directory_iterator 默认不跟随符号链接,这是安全的默认行为。但硬链接仍需额外去重:
- 用
entry.inode_number()(POSIX)或entry.status().st_ino判断是否为同一 inode(Linux/macOS) - Windows 没有 inode,可用
entry.status().st_filesize+entry.status().st_mtime+ 文件路径哈希粗略去重(不绝对可靠,但比不处理好) - 更稳妥的做法是维护一个
std::set<:pair ino_t>></:pair>(POSIX)或std::set<:string></:string>(Windows,存完整路径)来记录已统计的文件标识
大目录下性能和内存要注意
递归遍历百万级小文件时,recursive_directory_iterator 内部会缓存大量 directory_entry 对象,可能触发频繁堆分配。实测在某些 libc++ 实现上比 libstdc++ 慢 2–3 倍。
- 用
std::filesystem::directory_iterator手动栈模拟递归,可控制每层深度并复用对象,减少内存抖动 - 批量读取(如每次处理 1000 个 entry 后清空局部变量)有助于降低峰值内存
- 若仅需近似值,可跳过某些子目录(如
.git、node_modules),加白名单过滤比事后排除更省 CPU
真正麻烦的不是代码写法,而是不同文件系统对“大小”的定义差异:NTFS 的压缩文件、APFS 的克隆文件、ext4 的稀疏文件,它们的 file_size() 和实际磁盘占用根本不同。除非业务明确要求“逻辑大小”,否则得提醒用户:C++ 算出来的数字,和资源管理器右键看到的“大小”可能永远对不上。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











