Python 同步文件夹
将基础文件夹下的文件,按照目录结构,同步到目标文件夹下,如果目标文件夹下没有相应的目录结构,就创建目录,然后再将基础文件夹下的文件同步到相应的目录下去。
import os
import shutil
import time
import hashlib
# MD5值
def getMD5(path):
f=open(path,'rb')
d5 = hashlib.md5() #生成一个hash的对象
with open(path,'rb') as f:
while True:
content = f.read(40960)
if not content:
break
d5.update(content) # 每次读取一部分,然后添加到hash对象里
# print('MD5 : %s' % d5.hexdigest())
return d5.hexdigest() # 打印16进制的hash值
# 装饰器,计时用的
def timer(func): # 高阶函数:以函数作为参数
def deco(*args,**kwargs): # 嵌套函数,在函数内部以 def 声明一个函数,接受 被装饰函数的所有参数
time1 = time.time()
func(*args,**kwargs)
time2 = time.time()
print('Elapsed %ss\n' % round(time2-time1,2))
return deco # 注意,返回的函数没有加括号!所以返回的是一个内存地址,而不是函数的返回值
@timer
def compare(baseFolder,targetFolder,content_compare='y'):
'''
:param baseFolder: 基础文件夹,将基础文件夹中的文件按照相应的目录结构同步到目标文件夹中。
:param targetFolder: 目标文件夹
:content_compare: 是否比对两个文件的内容,默认比对,防止文件内容有更改。参数值如果不是'y',则不比对内容,只判断目标文件夹是否有同名文件,有就跳过,没有就复制过去。
'''
n = 0
for path,subpath,files in os.walk(baseFolder):
for file in files:
# 获取文件的绝对路径
absPath = os.path.join(path,file)
# 文件的后半截路径,即文件的相对路径
file_path = absPath.replace(baseFolder,'')
# 去掉路径前面的\
if file_path[:1] == '\\':
file_path = file_path[1:]
# 替换目录末尾的\
if targetFolder[:1] == '\\':
targetFolder = targetFolder[1:]
# 判断目标文件夹是否有相应的文件
filePath = os.path.join(targetFolder,file_path)
# 创建文件夹路径
fileFolder = os.path.dirname(filePath)
# 如果目标文件夹不存在此文件
if not os.path.exists(filePath):
os.makedirs(fileFolder,exist_ok=True)
# 复制文件
shutil.copy(absPath,fileFolder)
print(f'\n {absPath} --------------> {filePath}')
else: # 如果目标文件夹已经存在某文件
# 如果要对比两个文件的内容
if content_compare == 'y':
# 先对比两个文件的修改时间(谁的时间越大,代表谁的内容越新)
baseTime = os.stat(absPath).st_mtime
targetTime = os.stat(filePath).st_mtime
if baseTime-targetTime > 0:
# 比了时间,再比一下MD5。如果MD5也不同,就将这个时间最新的文件复制过去
baseMD5 = getMD5(absPath)
targetMD5 = getMD5(filePath)
if baseMD5 != targetMD5:
os.unlink(filePath)
shutil.copy(absPath,fileFolder)
print(f'\n {absPath} --------------> {filePath}')
else:
# MD5相同,而目标文件夹中的时间又小,就将修改时间改大,防止下次运行此脚本时再对比一遍MD5,浪费时间
# 修改文件的访问和修改时间,改成当前系统时间
os.utime(filePath)
n+=1
print("\r%s: Has scanned %s files. "%(baseFolder,n),end='' )
if __name__ == '__main__':
print('----------Copying the files of BaseFolder to TargetFolder.----------\n')
base = input('Input base folder:')
target = input('Input target folder:')
# 当有相同文件时,是否对比文件内容,把最新的同步过去,适用于经常变动的文件,如脚本,文档
content_compare = input('Compare content? y/n: ').lower()
if base == '':
compare(r'D:\备份',r'G:\备份')
compare(r'D:\software',r'G:\software')
compare(r'E:\文档',r'G:\document')
else:
compare(base,target,content_compare)