来自GTP
支持忽略文件及文件夹
注意: clear_ingore_subfolder会删除过滤的文件夹, 若目标文件夹存才
# -*- coding: utf-8 -*-
# ====> 同步文件 <==== #
import os
import shutil
import time
import traceback
# 忽略同步的文件夹, 默认为源文件夹下面的文件夹名称, 源文件夹下面的子文件夹格式如: os.path.join('api', 'doc')
ignore_dirs = ['.git', '__pycache__', '.idea', 'files', os.path.join('api', 'doc')]
# 忽略同步的文件名称
ignore_files = ['app.log']
# 更新计数器
update_count = 0
# 同步文件
def sync_files(source_folder, destination_folder, source_ignore_dirs_relative_path):
for root, dirs, files in os.walk(source_folder):
# 处理文件
for file in files:
source_file = os.path.join(root, file)
ignore_state = False
for pp in source_ignore_dirs_relative_path:
file_relative_path = os.path.relpath(source_file, pp)
if not file_relative_path.startswith('..'):
ignore_state = True
break
if not ignore_state:
relative_path = os.path.relpath(source_file, source_folder)
destination_file = os.path.join(destination_folder, relative_path)
if not os.path.exists(destination_file) or (
os.path.exists(destination_file) and os.stat(source_file).st_mtime > os.stat(
destination_file).st_mtime):
if file not in ignore_files:
increase_counter()
shutil.copy(source_file, destination_file)
print(f"Copied 【file】 [{source_file}] => [{destination_file}]")
# 处理子文件夹
for subdir in dirs:
source_subdir = os.path.join(root, subdir)
relative_path = os.path.relpath(source_subdir, source_folder)
destination_subdir = os.path.join(destination_folder, relative_path)
if not os.path.exists(destination_subdir):
ignore_state = False
for pp in source_ignore_dirs_relative_path:
file_relative_path = os.path.relpath(source_subdir, pp)
if not file_relative_path.startswith('..'):
ignore_state = True
break
if not ignore_state:
increase_counter()
shutil.copytree(source_subdir, destination_subdir)
print(f"Copied 【dir】 [{source_subdir}] => [{destination_subdir}]")
else:
sync_files(source_subdir, destination_subdir, source_ignore_dirs_relative_path)
# 清理忽略的子文件夹
def clear_ingore_subfolder(destination_folder):
destination_ignore_dirs_relative_path = [f"{os.path.join(destination_folder, item)}" for item in ignore_dirs]
for igp in destination_ignore_dirs_relative_path:
if os.path.exists(igp) and os.path.isdir(igp):
shutil.rmtree(igp)
print(f"Cleard ignore 【dir】 {igp} ")
# 更新计数器(文件夹算1次)
def increase_counter():
global update_count
update_count += 1
# 执行
# source_folder: 源文件夹
# destination_folder: 目标文件夹
def run(source_folder, destination_folder):
print(f'start sync file, source:【{source_folder}】, destination:【{destination_folder}】 ...')
try:
st = time.time()
source_ignore_dirs_relative_path = [f"{os.path.join(source_folder, item)}" for item in ignore_dirs]
sync_files(source_folder, destination_folder, source_ignore_dirs_relative_path)
clear_ingore_subfolder(destination_folder)
print(
f'√√√ sync file completed, time consuming:[{round(time.time() - st, 2)}]second, updated file size:{update_count} √√√')
except Exception:
print(f'××× sync file error ×××')
traceback.print_exc()
if __name__ == '__main__':
source_folder = "D:\\synct\\s"
destination_folder = "D:\\synct\\t"
run(source_folder, destination_folder)