用 Python 生成文件清单:把路径、大小和 SHA-256 分开记录
问题与输出约定
交付一批资料时,目录截图可以说明文件看起来存在,却不便于逐项核对内容。下面用Python标准库生成一份清单,每行记录相对路径、字节大小、SHA-256和状态。示例适用于普通、已停止修改的小型目录,不扫描系统目录,不自动删除或覆盖源文件。输出放在扫描目录之外,避免下一轮把清单自身纳入计算。
一段可运行的实现
在脚本旁建立sample_data目录,将待核对文件放进去。使用Python 3.10或更新版本运行,结果写入manifest.json。读取采用分块方式,避免一次把整个大文件载入内存。
import hashlib
import json
from pathlib import Path
root = Path("sample_data").resolve(strict=True)
rows = []
for path in sorted(root.rglob("*")):
if path.is_symlink() or not path.is_file():
continue
try:
before = path.stat()
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
after = path.stat()
stable = (before.st_size, before.st_mtime_ns) == (after.st_size, after.st_mtime_ns)
rows.append({"path": path.relative_to(root).as_posix(),
"size": after.st_size,
"sha256": digest.hexdigest() if stable else None,
"status": "ok" if stable else "changed_during_read"})
except OSError as exc:
rows.append({"path": path.relative_to(root).as_posix(),
"status": "error", "error_type": type(exc).__name__})
Path("manifest.json").write_text(
json.dumps(rows, ensure_ascii=False, indent=2), encoding="utf-8")
为什么同时记录路径和哈希
路径描述文件在这批交付资料中的位置,哈希用于比较读取到的字节内容。文件改名后,路径改变但内容哈希可以不变;同一个路径被新文件覆盖,路径不变但哈希通常会改变。只用文件名或大小作为一致性证据都不充分。对比两份清单时,应先按相对路径建立对应关系,再比较状态、大小和摘要,不要把缺失的条目当作一致。
读取失败不能伪装成空文件
示例将权限不足、文件消失等OSError记录为error,并保留异常类型。真正的空文件仍然能够得到确定的SHA-256,不能用空字符串代表所有异常。读前读后比较大小和纳秒修改时间,可以发现一部分并发修改;这并不构成原子快照。如果目录还在持续写入,应先停止写入、使用合适的快照机制,或者接受本轮结果需要重跑。
适用边界与验证方法
代码主动跳过符号链接,避免把链接目标混入这份普通目录清单;它不是面向不可信目录树的安全扫描器。可以用同内容不同文件名、同长度不同内容、空文件和中文文件名构造小样本,核对结果。摘要相同适合判断日常拷贝一致性,但不能证明来源可信;若攻击者同时替换文件和清单,单纯重新计算哈希无法识别。因此应通过可信渠道保存或传递参考清单。
参考资料
Python官方文档:hashlib — Secure hashes and message digests,https://docs.python.org/3/library/hashlib.html 。示例代码为本文独立编写,未复制文档示例。
说明:本文由 AI 辅助撰写,配图为自制说明图,示例数据为演示数据。

用标准库生成JSON文件清单,逐项记录读取失败和读取期间变更,说明哈希比对能够解决的问题及其边界。
浙公网安备 33010602011771号