场景引入
你的工作资料只存在电脑本地?一旦硬盘损坏、电脑丢失或中勒索病毒,几年的心血瞬间归零。
专业的做法是 定期备份:把重要文件夹同步到移动硬盘或云端。手动复制粘贴容易忘记,本节教你用 python + windows 定时任务实现全自动备份。
技术原理
备份的核心是 增量同步——只复制新增和修改的文件,避免每次都全量拷贝。
源文件夹(工作资料)
↓ 对比差异
备份文件夹(移动硬盘)
↓ 只复制变更
同步完成
同步策略
| 策略 | 说明 | 适用场景 |
|---|---|---|
| 增量同步 | 只复制新增/修改的文件 | 日常备份(推荐) |
| 全量复制 | 每次全部复制 | 首次备份 |
| 镜像同步 | 备份端删除源端已删除的文件 | 精确镜像 |
| 差异备份 | 只备份修改的部分(节省空间) | 大型文件 |
环境准备
pip install shutil
shutil 是 python 内置模块,无需额外安装。
完整代码
import os
import shutil
import time
from pathlib import path
from datetime import datetime
# ==================== 方案 1:增量文件同步 ====================
def sync_folders(source_dir, backup_dir, log_file=none):
"""
将源文件夹增量同步到备份文件夹
参数:
source_dir: 源文件夹路径(原始文件)
backup_dir: 备份文件夹路径(目标位置)
log_file: 日志文件路径(可选)
"""
source = path(source_dir)
backup = path(backup_dir)
if not source.exists():
print(f"错误:源目录 {source_dir} 不存在!")
return false
# 创建备份目录
backup.mkdir(parents=true, exist_ok=true)
files_copied = 0
files_updated = 0
files_skipped = 0
total_size = 0
log_lines = []
def log(msg):
print(msg)
log_lines.append(msg)
log(f"[{datetime.now().strftime('%y-%m-%d %h:%m:%s')}] 开始同步")
log(f"源目录: {source}")
log(f"备份目录: {backup}")
log("-" * 50)
# 遍历源目录所有文件
for file_path in source.rglob('*'):
if file_path.is_file():
# 计算相对路径
rel_path = file_path.relative_to(source)
dest_path = backup / rel_path
# 判断是否需要复制
need_copy = false
if not dest_path.exists():
need_copy = true
action = "新增"
elif file_path.stat().st_mtime > dest_path.stat().st_mtime:
need_copy = true
action = "更新"
elif file_path.stat().st_size != dest_path.stat().st_size:
need_copy = true
action = "大小变更"
if need_copy:
# 确保目标目录存在
dest_path.parent.mkdir(parents=true, exist_ok=true)
try:
shutil.copy2(str(file_path), str(dest_path))
file_size = file_path.stat().st_size
total_size += file_size
if action == "新增":
files_copied += 1
else:
files_updated += 1
log(f" [{action}] {rel_path} ({file_size / 1024:.1f} kb)")
except exception as e:
log(f" [失败] {rel_path}: {e}")
else:
files_skipped += 1
# 汇总报告
log("-" * 50)
log(f"同步完成!")
log(f"新增文件: {files_copied}")
log(f"更新文件: {files_updated}")
log(f"跳过文件: {files_skipped}")
log(f"总复制量: {total_size / 1024 / 1024:.2f} mb")
# 写入日志
if log_file:
path(log_file).parent.mkdir(parents=true, exist_ok=true)
with open(log_file, 'a', encoding='utf-8') as f:
f.write('\n'.join(log_lines) + '\n\n')
return true
# ==================== 方案 2:打包压缩备份 ====================
def backup_as_zip(source_dir, backup_dir):
"""
将整个文件夹打包为带日期的 zip 压缩包
"""
source = path(source_dir)
backup = path(backup_dir)
backup.mkdir(parents=true, exist_ok=true)
date_str = datetime.now().strftime('%y%m%d_%h%m%s')
folder_name = source.name
zip_name = f"{folder_name}_备份_{date_str}"
zip_path = shutil.make_archive(
str(backup / zip_name),
'zip',
str(source)
)
file_size = os.path.getsize(zip_path) / 1024 / 1024
print(f"备份完成: {zip_path} ({file_size:.2f} mb)")
return zip_path
# ==================== 方案 3:保留多个历史版本 ====================
def versioned_backup(source_dir, backup_base_dir, keep_versions=5):
"""
保留多个历史版本的备份(类似时间机器)
参数:
source_dir: 源目录
backup_base_dir: 备份根目录
keep_versions: 保留最近的几个版本
"""
source = path(source_dir)
backup_base = path(backup_base_dir)
backup_base.mkdir(parents=true, exist_ok=true)
# 按日期创建版本文件夹
date_str = datetime.now().strftime('%y%m%d_%h%m%s')
version_dir = backup_base / f"v{date_str}"
# 全量复制
if version_dir.exists():
shutil.rmtree(version_dir)
shutil.copytree(str(source), str(version_dir))
print(f"已创建备份版本: {version_dir}")
# 清理旧版本(保留最新的 keep_versions 个)
versions = sorted(backup_base.iterdir())
while len(versions) > keep_versions:
old_version = versions.pop(0)
if old_version.is_dir():
shutil.rmtree(old_version)
print(f"已清理旧版本: {old_version}")
# ==================== 使用示例 ====================
if __name__ == "__main__":
# 配置项
source = r"d:\工作资料"
backup = r"e:\备份\工作资料"
# 方案 1:增量同步
sync_folders(source, backup, log_file="backup_log.txt")
# 方案 2:打包压缩
# backup_as_zip(source, r"e:\备份")
# 方案 3:版本化备份(保留 5 个版本)
# versioned_backup(source, r"e:\备份\版本历史", keep_versions=5)
代码逐行解析
1. 增量同步判断逻辑
if not dest_path.exists():
need_copy = true # 新文件
elif file_path.stat().st_mtime > dest_path.stat().st_mtime:
need_copy = true # 修改时间更新
elif file_path.stat().st_size != dest_path.stat().st_size:
need_copy = true # 大小变化
三层判断确保:新增文件、修改过的文件、大小变化的文件都会被复制。
2. shutil.copy2 保留元数据
shutil.copy2(str(file_path), str(dest_path))
copy2 与 copy 的区别:copy2 会同时复制文件的元数据(修改时间、创建时间等),保证备份文件的属性与源文件一致。
3. 递归遍历
for file_path in source.rglob('*'):
.rglob('*') 递归遍历所有子目录,等价于 os.walk() 但使用 pathlib 的面向对象语法。
进阶技巧
技巧 1:结合 windows 任务计划程序实现定时备份
创建一个 .bat 批处理文件:
@echo off python "d:\scripts\auto_backup.py"
打开"任务计划程序" → 创建基本任务 → 设置触发器(如每天 18:00)→ 指定批处理文件。
技巧 2:备份完成后弹出通知
import ctypes # windows 通知 ctypes.windll.user32.messageboxw(0, "备份完成!", "领慧备份助手", 0x40)
技巧 3:只备份特定类型的文件
# 只备份 .docx 和 .xlsx 文件
allowed_extensions = {'.docx', '.xlsx', '.pdf'}
for file_path in source.rglob('*'):
if file_path.is_file() and file_path.suffix.lower() in allowed_extensions:
# ... 同步逻辑
常见问题
q1:同步过程中断电/中断怎么办?
shutil.copy2 是逐个文件复制的,中断后重新运行脚本会自动跳过已完成的文件(通过修改时间判断)。
q2:备份占用空间太大?
使用方案 3(版本化备份)配合 keep_versions 限制历史版本数量。或者使用 zip 压缩:
import zipfile
with zipfile.zipfile(backup_path, 'w', zipfile.zip_deflated) as zf:
for file_path in source.rglob('*'):
if file_path.is_file():
arcname = file_path.relative_to(source)
zf.write(file_path, arcname)
q3:备份到网络驱动器/nas?
路径使用 unc 格式:
backup = r"\\192.168.1.100\shared\backup\工作资料"
总结
| 备份策略 | 函数 | 特点 |
|---|---|---|
| 增量同步 | sync_folders() | 只复制变更,速度快 |
| 压缩打包 | backup_as_zip() | 一个 zip 文件,方便传输 |
| 版本保留 | versioned_backup() | 可回溯历史版本 |
本节掌握了三种备份策略。推荐组合使用:日常增量同步 + 每周压缩打包 + 保留 3-5 个版本。
到此这篇关于python实现定时自动同步重要文件夹至移动硬盘或云端的文章就介绍到这了,更多相关python定时自动同步文件内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论