Python脚本:校验源与备份目录差异

所需库

pip3 install shutil
pip3 install argparse

代码

#!/usr/bin/python3
import os
import sys
import filecmp
import shutil
import argparse

def compareme(dir1, dir2):  # 递归获取更新项
    holderlist = []
    dircomp = filecmp.dircmp(dir1, dir2)
    only_in_one = dircomp.left_only  # 源目录新文件或目录
    diff_in_one = dircomp.diff_files  # 不匹配文件,源目录文件已发生变化

    # 将更新文件名或目录追加到holderlist
    holderlist.extend([os.path.abspath(os.path.join(dir1, x)) for x in only_in_one])
    holderlist.extend([os.path.abspath(os.path.join(dir1, x)) for x in diff_in_one])

    if len(dircomp.common_dirs) > 0:  # 判断是否存在相同子目录
        for item in dircomp.common_dirs:  # 递归子目录
            holderlist.extend(compareme(os.path.abspath(os.path.join(dir1, item)),
                                        os.path.abspath(os.path.join(dir2, item))))
    return holderlist

def copy_files(source_files, dir1, dir2):
    destination_files = []
    for item in source_files:  # 遍历返回的差异文件或文件目录清单
        relative_path = os.path.relpath(item, dir1)  # 计算相对路径
        destination_dir = os.path.join(dir2, relative_path)  # 目标目录

        if os.path.isdir(item):  # 如果差异路径为目录且不存在,则在备份目录中创建
            if not os.path.exists(destination_dir):
                os.makedirs(destination_dir)
        else:
            destination_files.append((item, destination_dir))
  
    return destination_files

def main():
    parser = argparse.ArgumentParser(description='Synchronize files between two directories.')
    parser.add_argument('dir1', help='Source directory')
    parser.add_argument('dir2', help='Backup directory')
    args = parser.parse_args()

    dir1 = os.path.abspath(args.dir1)
    dir2 = os.path.abspath(args.dir2)

    if not dir2.endswith('/'):
        dir2 += '/'  # 备份目录加“/”符

    source_files = compareme(dir1, dir2)  # 对比源目录与备份目录
    if source_files:
        print("Update items:")
        print(source_files)

        copy_pairs = copy_files(source_files, dir1, dir2)  # 获取源目录与备份目录文件清单
        for src, dest in copy_pairs:  # 进行复制操作
            shutil.copyfile(src, dest)
            print(f"Copied {src} to {dest}")

if __name__ == '__main__':
    main()