【Python】实现一个文件夹快照与比较工具
·
1. 工具简介
在日常开发、项目管理或备份场景中,我们经常需要知道某个文件夹中的文件是否发生变化,例如:
- 项目源码是否新增或修改文件?
- 数据集是否被不小心删除或篡改?
- 备份文件夹是否和上次一致?
本教程将教你如何编写一个简单的 Python 命令行工具,只基于文件内容哈希值(SHA256) 来检测变化。
2. 功能设计
该工具支持两个核心命令:
| 命令 | 作用 |
|---|---|
create |
创建当前文件夹的快照,保存为 JSON |
compare |
比较当前文件夹与指定快照文件的差异 |
命令行格式:
python snapshot.py <目录路径> <create|compare> <快照文件.json>
示例:
# 创建快照
python snapshot.py ./project create snapshot.json
# 比较快照
python snapshot.py ./project compare snapshot.json
3. 核心实现思路
-
遍历文件夹
- 递归遍历指定文件夹中的所有文件,并计算每个文件的 SHA256 哈希值。
-
快照格式
-
将快照保存为 JSON 文件,文件路径使用 POSIX 风格的
/分隔符,保证跨平台一致性。 -
快照文件结构示例:
{ "main.py": "a3f2f9c91b72e9f8d4f2...", "data/input.csv": "e49adf91c7dbe23ff03d..." }
-
-
比较逻辑
- 根据快照与当前文件夹的哈希值,分为三类:
- 新增文件:当前存在但快照中没有的文件
- 删除文件:快照中存在但当前不存在的文件
- 修改文件:快照和当前都存在,但哈希值不同
- 根据快照与当前文件夹的哈希值,分为三类:
4. 完整代码
下面是实现该工具的完整 Python 代码,只有一个文件,简单易用。
#!/usr/bin/env python3
import os
import sys
import json
import hashlib
from pathlib import Path
def calc_file_hash(file_path, chunk_size=8192):
"""计算文件的 SHA256 哈希值"""
sha256 = hashlib.sha256()
try:
with open(file_path, "rb") as f:
while chunk := f.read(chunk_size):
sha256.update(chunk)
except Exception as e:
print(f"[ERROR] Cannot read file: {file_path}, {e}", file=sys.stderr)
return None
return sha256.hexdigest()
def create_snapshot(directory: Path, output_file: Path):
"""创建快照文件,路径统一为 POSIX 风格"""
directory = directory.resolve()
snapshot = {}
for root, _, files in os.walk(directory):
for filename in files:
abs_path = Path(root) / filename
# 统一使用 "/" 作为分隔符
rel_path = abs_path.relative_to(directory).as_posix()
file_hash = calc_file_hash(abs_path)
if file_hash:
snapshot[rel_path] = file_hash
with open(output_file, "w", encoding="utf-8") as f:
json.dump(snapshot, f, indent=2, ensure_ascii=False)
print(f"[OK] Snapshot created: {output_file}")
def compare_snapshot(directory: Path, snapshot_file: Path):
"""比较当前目录与快照的差异"""
with open(snapshot_file, "r", encoding="utf-8") as f:
old_files = json.load(f)
base_dir = directory.resolve()
current_files = {}
for root, _, files in os.walk(base_dir):
for filename in files:
abs_path = Path(root) / filename
rel_path = abs_path.relative_to(base_dir).as_posix()
file_hash = calc_file_hash(abs_path)
if file_hash:
current_files[rel_path] = file_hash
# 计算差异
added = [f for f in current_files if f not in old_files]
deleted = [f for f in old_files if f not in current_files]
modified = [f for f in current_files if f in old_files and current_files[f] != old_files[f]]
# 输出结果
print("\nAdded files:")
for f in added:
print(f" + {f}")
print("\nDeleted files:")
for f in deleted:
print(f" - {f}")
print("\nModified files:")
for f in modified:
print(f" * {f}")
def main():
# 参数格式:python snapshot.py <directory> <create|compare> <snapshot.json>
if len(sys.argv) != 4:
print("Usage: python snapshot.py <directory> <create|compare> <snapshot.json>")
sys.exit(1)
directory = Path(sys.argv[1])
command = sys.argv[2].lower()
snapshot_file = Path(sys.argv[3])
if command == "create":
create_snapshot(directory, snapshot_file)
elif command == "compare":
compare_snapshot(directory, snapshot_file)
else:
print("Error: command must be 'create' or 'compare'")
sys.exit(1)
if __name__ == "__main__":
main()
5. 使用示例
假设有如下目录结构:
myfolder/
├─ file1.txt
├─ file2.txt
└─ subdir/
└─ image.png
创建快照
python snapshot.py ./myfolder create snapshot.json
生成的 snapshot.json 内容示例:
{
"file1.txt": "a3f2f9c91b72e9f8d4f2c5d9c0c3b...",
"file2.txt": "b74b9ff174c5e00e3e8f93b4c9f0a...",
"subdir/image.png": "e49adf91c7dbe23ff03dbf7839273..."
}
修改文件并比较
例如:
- 修改
file2.txt - 新增
notes.txt - 删除
subdir/image.png
执行比较命令:
python snapshot.py ./myfolder compare snapshot.json
输出结果:
Added files:
+ notes.txt
Deleted files:
- subdir/image.png
Modified files:
* file2.txt
6. 总结
通过本教程,我们实现了一个简洁高效的命令行工具,实现了以下功能:
- 记录文件夹的完整快照(基于文件内容哈希)。
- 快速比较当前文件夹与快照的差异。
- 跨平台兼容,结果统一、可读。
该工具非常适合日常开发和运维场景,帮助你高效地管理和追踪文件变化。
更多推荐

所有评论(0)