Python 3.11 无内置一键重建软链工具,但可用 pathlib、hashlib 和 os.symlink 在50行内实现稳定去重与软链替换,关键在于选用 blake2b 分块哈希、严谨路径处理及权限与平台兼容性兜底。

Python 3.11 本身不提供“一键去重建软链”的内置工具,但用 pathlib + hashlib + os.symlink 组合,50 行内就能稳定跑完常规去重和软链替换——关键在哈希策略选对、路径处理严谨、权限和平台兼容性提前兜底。
用 blake2b 做分块哈希,别用 md5 或全文件 sha256
全文件哈希在大文件(如视频、镜像)上极慢;md5 碰撞风险虽低但非零,且 Python 3.11 已默认禁用;sha256 计算开销比 blake2b 高约 30%。实际扫描中,先比大小,再对前 1MB + 后 1MB(或按固定块大小读取)做 blake2b,99% 的重复能秒判。
- 小文件(
- 大文件跳过中间部分时,务必用
file.seek()和file.read()显式控制,别依赖pathlib.Path.read_bytes()——它会把整个文件加载进内存 - Windows 上若目标盘符不同(如 C: → D:),
os.symlink会报OSError: [WinError 1314],需提前用os.path.samefile()或shutil.disk_usage()检查是否同卷
遍历目录时用 pathlib.Path.rglob(),但要过滤掉已存在的软链接
rglob("*") 简洁可靠,但若目录里已有软链指向其他位置,不加过滤会导致:1)重复计算目标文件哈希;2)误删原文件(如果逻辑写成“保留第一个,其余替换成链”)。必须在遍历时用 .is_file() and not .is_symlink() 双判断。
- Linux/macOS 下
.is_symlink()对软链本身返回True,对硬链返回False——这正是我们想要的 - Windows 默认不支持软链(除非管理员启用了开发者模式并以管理员运行脚本),此时
os.symlink()会抛OSError: symbolic link privilege not held,应捕获并 fallback 到跳过或打印提示 - 避免用
os.walk():它返回元组,路径拼接易出错;pathlib的/运算符更安全
建软链前必须 unlink() 原文件,并用 os.replace() 做原子替换
不能先建链再删原文件——中间失败会导致文件丢失。正确顺序是:1)计算好目标链接路径;2)target_path.unlink(missing_ok=True);3)os.symlink(src, target);4)确认成功后再删原文件。但更稳的做法是用 os.replace() 把原文件重命名成临时名,再建链,最后删临时文件。
立即学习“Python免费学习笔记(深入)”;
-
os.replace()在同文件系统下是原子操作,不会出现“链建了一半、原文件已删”的状态 - 软链目标路径必须是相对路径(推荐)或绝对路径,但不能是“相对于当前工作目录”的路径——要用
target_path.resolve().relative_to(anchor_dir)计算相对值,否则跨目录访问会断链 - Linux/macOS 上,
os.symlink(src, dst)的src是链里写的路径,不是 Python 当前路径;若用相对路径,它是相对于链所在目录解析的
最易被忽略的是 Windows 权限和符号链接语义差异:即使开了开发者模式,普通用户创建的软链在资源管理器里可能显示为普通文件夹,且某些备份工具会跳过它们。如果你的目标是节省空间而非统一访问入口,硬链接(os.link())更稳妥——但它要求源和目标在同一个文件系统,且不支持目录。


















