本文目录导读:

,常见的方法包括使用 rsync(Linux)、robocopy(Windows)或自定义脚本,以下是几种常用方案:
Linux/Unix 使用 rsync(推荐)
#!/bin/bash # sync_diff.sh - 同步差异文件 # 源目录和目标目录 SOURCE_DIR="/path/to/source/" DEST_DIR="/path/to/destination/" # 使用 rsync 同步差异文件 rsync -avz --delete --dry-run "$SOURCE_DIR" "$DEST_DIR" # 实际运行(去掉 --dry-run 才会真正同步) # rsync -avz --delete "$SOURCE_DIR" "$DEST_DIR"
rsync 常用参数:
-a: 归档模式(保留权限、时间等)-v: 详细输出-z: 压缩传输--delete: 删除目标端多余文件--dry-run: 预演,不实际执行
Windows 使用 robocopy
@echo off REM sync_diff.bat - Windows 差异文件同步 SET SOURCE_DIR=C:\path\to\source SET DEST_DIR=D:\path\to\destination REM 镜像模式(完全同步差异) robocopy %SOURCE_DIR% %DEST_DIR% /MIR /R:3 /W:10 REM 仅复制新文件和变更文件 robocopy %SOURCE_DIR% %DEST_DIR% /XO /R:3 /W:10
robocopy 常用参数:
/MIR: 镜像目录树(等同于/E+/PURGE)/XO: 排除旧文件(仅复制新文件)/R:3: 失败重试3次/W:10: 等待10秒重试
Python 自定义同步脚本
#!/usr/bin/env python3
# sync_diff.py - 自定义差异同步
import os
import hashlib
import shutil
from pathlib import Path
def get_file_hash(file_path):
"""获取文件 MD5 哈希"""
hash_md5 = hashlib.md5()
with open(file_path, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()
def sync_directories(source_dir, dest_dir, dry_run=False):
"""同步差异文件"""
source_dir = Path(source_dir)
dest_dir = Path(dest_dir)
# 遍历源目录
for source_file in source_dir.rglob("*"):
if source_file.is_file():
# 计算目标文件路径
relative_path = source_file.relative_to(source_dir)
dest_file = dest_dir / relative_path
need_copy = False
if not dest_file.exists():
need_copy = True
else:
# 比较文件哈希
if get_file_hash(source_file) != get_file_hash(dest_file):
need_copy = True
if need_copy:
if dry_run:
print(f"[DRY RUN] 需同步: {relative_path}")
else:
dest_file.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(source_file, dest_file)
print(f"已同步: {relative_path}")
# 使用示例
if __name__ == "__main__":
SOURCE = "/path/to/source"
DEST = "/path/to/destination"
# 先预览差异
sync_directories(SOURCE, DEST, dry_run=True)
# 确认后实际同步
# sync_directories(SOURCE, DEST)
双向同步脚本
#!/usr/bin/env python3
# two_way_sync.py - 双向同步
import os
import shutil
import filecmp
from pathlib import Path
def two_way_sync(dir1, dir2):
"""双向同步两个目录"""
dir1 = Path(dir1)
dir2 = Path(dir2)
# 比较目录
comparison = filecmp.dircmp(dir1, dir2)
# 处理 dir1 有但 dir2 没有的文件
for file in comparison.left_only:
src = dir1 / file
dst = dir2 / file
if src.is_file():
shutil.copy2(src, dst)
print(f"复制到 dir2: {file}")
# 处理 dir2 有但 dir1 没有的文件
for file in comparison.right_only:
src = dir2 / file
dst = dir1 / file
if src.is_file():
shutil.copy2(src, dst)
print(f"复制到 dir1: {file}")
# 处理共同但不同的文件(取较新版本)
for file in comparison.diff_files:
file1 = dir1 / file
file2 = dir2 / file
time1 = os.path.getmtime(file1)
time2 = os.path.getmtime(file2)
if time1 > time2:
shutil.copy2(file1, file2)
print(f"覆盖 dir2 的: {file}")
elif time2 > time1:
shutil.copy2(file2, file1)
print(f"覆盖 dir1 的: {file}")
# 递归处理子目录
for subdir in comparison.common_dirs:
two_way_sync(dir1 / subdir, dir2 / subdir)
# 使用示例
two_way_sync("/path/to/dir1", "/path/to/dir2")
使用 inotify 实时同步
#!/bin/bash
# realtime_sync.sh - 实时监控同步
SOURCE_DIR="/path/to/source"
DEST_DIR="/path/to/destination"
# 需要安装 inotify-tools
# apt-get install inotify-tools # Debian/Ubuntu
# yum install inotify-tools # CentOS/RHEL
inotifywait -m -r -e modify,create,delete,move "$SOURCE_DIR" --format '%w%f %e' |
while read file event
do
echo "检测到变更: $file ($event)"
# 根据事件类型处理
case "$event" in
CREATE*|MODIFY*)
rsync -avz "$file" "$DEST_DIR/$(basename $file)"
;;
DELETE*)
dest_file="$DEST_DIR/$(basename $file)"
[ -f "$dest_file" ] && rm "$dest_file"
;;
MOVED_FROM*)
dest_file="$DEST_DIR/$(basename $file)"
[ -f "$dest_file" ] && rm "$dest_file"
;;
esac
done
选择建议
| 场景 | 推荐方案 |
|---|---|
| Linux 服务器间同步 | rsync |
| Windows 系统 | robocopy |
| 需要自定义逻辑 | Python 脚本 |
| 双向同步 | Python 双向同步脚本 |
| 实时监控同步 | inotify + rsync |
| 跨平台 | Python 脚本 |
注意: 生产环境执行同步前,务必先使用 --dry-run 或测试模式预览变更内容,确认无误后再真正执行同步操作。