std::filesystem::space仅返回路径所在文件系统的空间数值,不提供挂载点、设备名或文件系统类型等信息;需结合系统API(如Linux读/proc/mounts)获取挂载点后再调用space查询。

用 std::filesystem::space 获取剩余空间,但别指望它返回挂载点
直接说结论:std::filesystem::space 只能告诉你某个路径所在文件系统的总空间、可用空间和空闲空间(space_info 结构体),但它**完全不提供挂载点路径、设备名、文件系统类型或挂载选项等信息**。这是 C++ 标准库的明确限制——它抽象掉了底层挂载细节。
常见错误是传入 "/" 或 "C:/" 就以为能拿到“系统盘挂载信息”,结果只得到数字,连这个空间属于哪个设备都不知道。
-
std::filesystem::space的输入是路径,输出是纯数值,和statvfs()/GetDiskFreeSpaceEx()类似,但更跨平台 - Windows 下它可能映射到
GetDiskFreeSpaceEx;Linux/macOS 下通常调用statvfs,但屏蔽了f_mntfromname、f_fstypename等字段 - 如果你需要挂载点列表(比如列出
/、/home、/mnt/data),std::filesystem本身做不到,必须系统 API 配合
Linux 下用 /proc/mounts 解析挂载点,再逐个查空间
Linux 最轻量可靠的方式就是读取 /proc/mounts(或更规范的 /proc/self/mounts),按空格分割每行,提取第 2 字段(挂载点)和第 3 字段(文件系统类型),过滤掉 proc、sysfs、devtmpfs 等伪文件系统。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 用
std::ifstream逐行读"/proc/mounts",跳过注释和空行 - 对每个挂载点路径,调用
std::filesystem::space(mount_point)获取空间数据 - 注意权限:某些挂载点(如
/boot/efi)可能因权限不足导致space()抛std::filesystem::filesystem_error,需捕获处理 - 避免重复:同一设备可能被挂载多次(bind mount),可额外解析
/proc/mountinfo或用statfs.f_fsid去重,但多数场景不需要
示例片段(不带错误处理):
std::ifstream mounts("/proc/mounts");
std::string line, device, mount_point, fstype;
while (std::getline(mounts, line)) {
std::istringstream iss(line);
if (iss >> device >> mount_point >> fstype) {
if (fstype == "ext4" || fstype == "xfs" || fstype == "btrfs") {
try {
auto s = std::filesystem::space(mount_point);
std::cout << mount_point << " (" << fstype << "): "
<< s.available / (1024*1024) << " MiB available
";
} catch (...) { /* 忽略无权访问的挂载点 */ }
}
}
}
Windows 下用 GetVolumeInformation + GetDiskFreeSpaceEx 补全挂载点
Windows 没有统一挂载点概念,但每个驱动器根目录(如 "C:\"、"D:\")本质就是挂载点。你需要先枚举所有逻辑驱动器,再分别获取其卷标、文件系统类型和空间信息。
关键点:
- 用
GetLogicalDrives()获取位掩码,再用for (char c = 'A'; c 构造 <code>c + ":\\"路径尝试 - 对每个有效路径,调用
GetVolumeInformation获取卷标(lpVolumeNameBuffer)和文件系统名(lpFileSystemNameBuffer) - 再用
GetDiskFreeSpaceEx获取空间,结果与std::filesystem::space一致,但多了元数据 -
std::filesystem::space在 Windows 下其实就封装了GetDiskFreeSpaceEx,所以两者数值相同,只是前者丢弃了卷信息
注意:网络驱动器(Z:\ 映射自 SMB)也能被枚举并查空间,但 GetVolumeInformation 对它们可能返回空卷标或 "Network" 类型。
跨平台封装时,别硬套 std::filesystem 命名,要分层设计
试图写一个“跨平台挂载点查询函数”并命名为 list_mount_points() 是合理的,但**不能把它塞进 std::filesystem 命名空间,也不该假装它是标准库一部分**。实际项目中应明确分层:
- 底层:平台专用实现(
linux_mounts.cpp/windows_volumes.cpp),导出统一结构体如struct MountInfo { std::string path; std::string fs_type; uint64_t total; uint64_t available; } - 中间层:用
std::filesystem::space做空间查询,但仅作为工具函数,不参与挂载发现逻辑 - 上层业务:只依赖
MountInfo列表,不关心来源是/proc/mounts还是GetLogicalDrives
最容易被忽略的一点:挂载点路径的“有效性”不是静态的。Linux 上 umount /mnt/usb 后,之前查到的路径仍存在但 space() 会失败;Windows 上拔掉 USB 盘,GetDiskFreeSpaceEx 返回 FALSE。所有调用都得带异常/错误检查,不能假设列表一次获取就永久有效。


















