必须读取二进制内容并计算SHA-256哈希比对,而非依赖std::filesystem::equivalent()或last_write_time();需跳过符号链接、统一路径基准、分块读取、捕获权限异常,并显式处理空目录以满足结构一致性要求。

用 std::filesystem 遍历目录并逐文件比对哈希值
直接用 std::filesystem::equivalent() 只能判断路径是否指向同一实体(硬链接或挂载点),不能校验内容;真正要确认“内容完全一致”,必须读取每个文件的二进制内容并比对。推荐做法是为每个文件计算 SHA-256(或 MD5,但 SHA-256 更抗碰撞),再按路径结构组织哈希映射表。
关键点在于:跳过符号链接(除非你明确想追踪)、忽略无关元数据(修改时间、权限)、统一处理路径分隔符(/ 和 视为等价)。
- 使用
std::filesystem::is_regular_file()过滤掉目录、socket、设备文件等非普通文件 - 对每个文件用
std::ifstream以std::ios::binary模式打开,分块读取(如 64KB),喂给 OpenSSL 或boost::uuid::sha256计算哈希——C++20 标准库不提供哈希函数,必须引入外部实现 - 相对路径作为键:用
std::filesystem::relative(path, root)统一基准,避免因绝对路径不同导致误判
遇到同名但内容不同的文件时,std::filesystem::last_write_time() 不可靠
仅靠修改时间判断文件是否相同是常见误区。NFS 挂载、容器内文件系统、备份还原过程都可能导致时间戳失真,甚至人为 touch 修改过时间但内容未变。实测中,两个 SHA-256 值相同的文件,last_write_time() 差几秒很常见;反之,时间戳一致却内容不同也并非罕见(比如 rsync --times 保留时间但传输出错)。
所以时间戳只能当快速筛选层(先跳过时间明显不同的),绝不能替代内容比对。
立即学习“C++免费学习笔记(深入)”;
- 若想加速,可先比对文件大小:
file_size()不同则直接判定不一致,避免无效哈希计算 - 大小相同时再计算哈希——这是最实用的剪枝策略
- 注意:空文件大小为 0,但多个空文件哈希值全相同,需确保路径结构也匹配
Windows 下长路径和权限错误会导致 std::filesystem::directory_iterator 抛异常
默认情况下,std::filesystem::directory_iterator 在遇到无法访问的子目录(如 System Volume Information)或权限不足的文件时会抛 std::filesystem::filesystem_error,整个遍历中断。这不是 bug,而是标准行为。
必须显式捕获并跳过,否则程序崩溃或漏检。
- 用
std::filesystem::recursive_directory_iterator替代普通迭代器,并配合options = std::filesystem::directory_options::skip_permission_denied - 仍需 try/catch 包裹,因为
skip_permission_denied仅对权限错误有效,对损坏的符号链接、IO 错误等仍可能抛异常 - Windows 路径长度超
MAX_PATH(260)时,需在路径前加\\?\前缀——std::filesystem在 C++17 中已自动处理,但某些旧版 MSVC 工具链(如 VS2017 Update 8 前)需手动启用/Zi和 manifest
两个目录结构不同但文件内容一致,算“完全一致”吗?
答案取决于你的定义。严格来说,“内容完全一致”隐含两层含义:所有文件存在且内容相同 + 目录树结构(包括空子目录)完全相同。很多工具(如 rsync --dry-run)只关注文件,忽略空目录;而备份一致性校验往往要求结构也一致。
这意味着你不仅要收集所有 regular_file 的哈希,还得记录哪些路径是空目录——可用 std::filesystem::is_empty() 判断,然后把空目录路径也纳入比对集合(值设为特殊标记如 "<empty-dir>"</empty-dir>)。
- 若接受“结构可不同,只要文件集一致”,就只需比对所有普通文件的
(relpath, hash)对,忽略目录项 - 若要求结构一致,空目录必须参与比对,且不能被
recursive_directory_iterator自动跳过(它默认不迭代空目录) - 注意:某些文件系统(如 ext4)对空目录的 inode 时间戳可能随父目录操作更新,但内容校验不关心这个——只要目录存在且为空,就算结构一致


















