文件迁移验收:为什么大小一样,还要比对内容哈希
文件复制结束后,最容易看到的是“总容量差不多”。但文件长度相同,只能说明长度一致,不能说明内容一致。迁移网盘、课程资料或同步目录时,我更愿意把路径、长度、内容和业务状态分开验收。
本文使用小型演示文件说明核对思路,不包含真实账号、凭证或个人文档。文章由 AI 协助整理,适用于理解和设计自己的只读核查流程。
一个最小反例
两个文件内容分别是 abcd 和 abce,都是4字节。按文件数量和长度统计,它们完全一样,但最后一个字节已经不同。
import hashlib
left = b"abcd"
right = b"abce"
print(len(left), len(right))
print(hashlib.sha256(left).hexdigest())
print(hashlib.sha256(right).hexdigest())
这个示例不需要连接服务器,也不会修改任何业务数据。它说明“大小一致”和“内容一致”是两个不同层次的判断。
第一层:先定义要保留的集合
扫描前先确定范围,例如哪些目录是正文,哪些是可重新生成的依赖,哪些是历史版本。范围需要事先确认,不能扫描完成后再把对不上的文件都归为“缓存”。
历史版本和冲突文件尤其需要单独处理。同名文件可能是不同内容,不同名称也可能保存了相同内容。当前版本与历史版本都存在时,应保留它们各自的来源,不要为追求“目录完全一致”而覆盖已经确认需要保留的版本。
第二层:路径和长度核对
清单应至少记录相对路径、文件类型和字节数。路径最好用 JSON 等结构化格式保存,不要假设文件名里没有空格、制表符或换行。
对于符号链接,要先决定核对链接本身还是链接目标。未明确范围时,不应该悄悄跟随链接扫描到其他目录。硬链接也会影响按路径统计的容量,不能把目录项数量当作独立物理文件数量。
第三层:按块读取内容哈希
下面这个函数只读取单个普通文件的内容,按块计算 SHA-256,不会把整个大文件一次装进内存:
from pathlib import Path
import hashlib
def sha256_file(path):
digest = hashlib.sha256()
with Path(path).open("rb") as stream:
while True:
block = stream.read(1024 * 1024)
if not block:
break
digest.update(block)
return digest.hexdigest()
读取权限不足、文件在读取途中消失、连接中断,都应该记录为“本次未完成核验”,不能记成空文件,也不能当作哈希相同。
如果源文件仍在写入,一次哈希计算也不保证得到一个稳定版本。正式切换前应安排一致性窗口,必要时暂停相关写入,再核对最后增量。暂停写入属于服务操作,需要另行安排,不能混在最初的只读调查里。
第四层:业务状态也要核验
对于由数据库管理的网盘,文件内容只是其中一部分。分享标识、目录关联、访问权限、数据库状态和访问入口也影响旧链接能否使用。因此,“文件哈希全部一致”并不等于“旧分享已经全部恢复”。
反过来,网页首页能打开,也不代表每个分享都能下载。可以分开记录:程序是否运行、首页是否响应、选定分享是否能访问、下载内容是否与预期一致。涉及访问次数限制的分享,应事先规划验证方式,避免核查本身消耗不必要的次数。
怎样形成可以执行的结论
我会把结果分成四类:已证明存在且内容相同、存在但内容不同、目标缺失、因错误尚未验证。对于差异,只给出路径、大小、哈希和可解释的内容差别,由文件所有者决定保留哪一份。
等保留范围、文件内容和业务访问都验收完成,再处理源端清理。这样每一个“可以删了”的结论,都能追溯到具体证据,而不只是同步界面上的一个完成百分比。
- 点赞
- 收藏
- 关注作者
评论(0)