Skip to content

同步目录

Python

python
import argparse
import shutil
from pathlib import Path


class FileSynchronizer:
    def __init__(self, source_dir, destination_dir):
        self.source_dir = Path(source_dir)
        self.destination_dir = Path(destination_dir)
        self.file_count = 0
        self.dir_count = 0

    def get_all_files_recursive(self, directory):
        for item in directory.glob('*'):
            if not item.is_dir():
                yield item
            else:
                yield from self.get_all_files_recursive(item)

    def copy_file(self, source_file, destination_file):
        print(f'Copying file "{source_file}" to "{destination_file}"')
        shutil.copy2(str(source_file), str(destination_file))

    def copy_directory(self, source_dir, destination_dir):
        print(f'Copying directory "{source_dir}" to "{destination_dir}"')
        shutil.copytree(str(source_dir), str(destination_dir))

    def synchronize_file(self, source_file, destination_file):
        print(f'Synchronizing file "{source_file}" to "{destination_file}"')
        shutil.copy2(str(source_file), str(destination_file))

    def sync_dir(self):
        for source_file in self.get_all_files_recursive(self.source_dir):
            relative_path = source_file.relative_to(self.source_dir)
            destination_file = self.destination_dir / relative_path

            source_dirname = source_file.parent
            destination_dirname = destination_file.parent

            if not destination_dirname.exists():
                self.copy_directory(source_dirname, destination_dirname)
                self.dir_count += 1

            if not destination_file.exists():
                self.copy_file(source_file, destination_file)
                self.file_count += 1
            else:
                source_mtime = source_file.stat().st_mtime
                dest_mtime = destination_file.stat().st_mtime

                if source_mtime > dest_mtime:
                    self.synchronize_file(source_file, destination_file)
                    self.file_count += 1

        print(f'Total files copied: {self.file_count}')
        print(f'Total directories copied: {self.dir_count}')


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('source_dir', help='Source directory')
    parser.add_argument('destination_dir', help='Destination directory')
    args = parser.parse_args()

    synchronizer = FileSynchronizer(args.source_dir, args.destination_dir)
    synchronizer.sync_dir()
    synchronizer = FileSynchronizer(args.destination_dir, args.source_dir)
    synchronizer.sync_dir()

Released under the MIT License.