Python批量同步两个文件夹教程
用Python对比源目录和目标目录,自动复制新增文件、更新修改过的文件、删除目标端多余文件,实现双向/单向文件夹同步。
场景痛点
工作文件在公司电脑改完,回家想接着用,每次手动复制整个文件夹,覆盖来覆盖去,不知道哪些是新增的、哪些改过的,还经常漏文件。写个同步脚本,源文件夹和目标文件夹一比,新增的自动复制、改过的自动更新、目标端多余的自动删掉,一键完成,跟网盘同步一样。
用到的库
pip install openpyxl
核心用标准库 os、pathlib、shutil,同步日志用 openpyxl。
完整代码
import os
import shutil
from pathlib import Path
from openpyxl import Workbook
def scan_dir(root: Path) -> dict:
"""扫描目录,返回 {相对路径: (大小, 修改时间戳)} 字典。"""
info = {}
for dirpath, _, filenames in os.walk(root):
for name in filenames:
p = Path(dirpath) / name
rel = str(p.relative_to(root))
try:
stat = p.stat()
except OSError:
continue
info[rel] = (stat.st_size, stat.st_mtime)
return info
def sync_folders(src: str, dst: str, delete_extra: bool = True):
"""
把 src 同步到 dst:
- src 有、dst 没有:复制
- 两边都有但大小或修改时间不同:用 src 覆盖 dst
- dst 有、src 没有:delete_extra=True 则删除
"""
src_root = Path(src)
dst_root = Path(dst)
dst_root.mkdir(parents=True, exist_ok=True)
src_info = scan_dir(src_root)
dst_info = scan_dir(dst_root)
actions = []
# 复制新增 / 更新变更
for rel, (size, mtime) in src_info.items():
src_file = src_root / rel
dst_file = dst_root / rel
if rel not in dst_info:
dst_file.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(src_file, dst_file)
actions.append(("新增", rel, ""))
else:
d_size, d_mtime = dst_info[rel]
if size != d_size or abs(mtime - d_mtime) > 1:
shutil.copy2(src_file, dst_file)
actions.append(("更新", rel, f"原大小{d_size}->{size}"))
# 删除目标端多余文件
if delete_extra:
for rel in dst_info:
if rel not in src_info:
dst_file = dst_root / rel
try:
dst_file.unlink()
actions.append(("删除", rel, ""))
except OSError as e:
actions.append(("删除失败", rel, str(e)))
return actions
def export_log(actions: list, out_path: str):
wb = Workbook()
ws = wb.active
ws.title = "同步日志"
ws.append(["操作", "相对路径", "备注"])
for act, rel, note in actions:
ws.append([act, rel, note])
ws.column_dimensions['A'].width = 10
ws.column_dimensions['B'].width = 70
ws.column_dimensions['C'].width = 30
wb.save(out_path)
if __name__ == "__main__":
SRC = r"D:\工作资料"
DST = r"E:\备份\工作资料"
actions = sync_folders(SRC, DST, delete_extra=True)
print(f"同步完成,共 {len(actions)} 个操作:")
from collections import Counter
stat = Counter(a[0] for a in actions)
for k, v in stat.items():
print(f" {k}: {v} 个")
export_log(actions, r"D:\工作资料\同步日志.xlsx")
print("日志已导出:D:\\工作资料\\同步日志.xlsx")
代码讲解
scan_dir 把目录下所有文件的相对路径、大小、修改时间扫成字典,键是相对路径,方便两个目录做集合对比。同步逻辑分三步:遍历源目录,目标端没有的复制过去(copy2 连时间戳一起复制);两边都有但大小或修改时间差超过1秒的,认为内容变了,覆盖过去;遍历目标端,源目录里没有的文件,delete_extra=True 就删掉。用1秒的误差阈值,避免文件系统时间精度差异导致不必要的覆盖。日志记录每一步操作,跑一次就知道同步了什么。
运行结果
控制台统计新增、更新、删除各多少个文件。E:\备份\工作资料 目录和 D:\工作资料 完全一致。同时生成 同步日志.xlsx,三列:操作类型、相对路径、备注。下次运行时没有变化就输出0个操作,说明已是最新。
注意事项
- 第一次跑建议
delete_extra=False,先只复制不删除,确认无误再开删除。 - 双向同步(两边都可能改文件)脚本不支持,这是单向从源到目标。
- 大文件同步时磁盘IO瓶颈明显,跨盘比同盘慢。
- 目标目录不要放在源目录里面,否则会递归同步自己。
- 想做计划任务每天自动跑,把脚本加到Windows任务计划程序即可。

更新时间:2026-09-14 21:25:18