將基礎文件夾下的文件,按照目錄結構,同步到目標文件夾下,如果目標文件夾下沒有相應的目錄結構,就創建目錄,然后再將基礎文件夾下的文件同步到相應的目錄下去。
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)