校驗源與備份目錄差異
有時我們無法確認備份與源目錄文件是否保持一致,包括源目錄中的新文件或目錄、更新文件或目錄有無成功同步,定期進行校驗,沒有成功則希望有針對性地進行補備份。
本例使用了filecmp模塊的left_only、diff_files方法遞歸獲取源目錄的更新項,再通過shutil.copyfile、os.makedirs方法對更新項進行復制,最終保持一致狀態。
#!/usr/bin/python3 # import os import sys import filecmp import re import shutil holderlist=[] def compareme(dir1,dir2): #遞歸獲取更新項函數 dircomp = filecmp.dircmp(dir1,dir2) only_in_one = dircomp.left_only #源目錄新文件或目錄 diff_in_one = dircomp.diff_files #不匹配文件,源目錄文件已經發生變化 dirpath = os.path.abspath(dir1) #定義源目錄絕對路徑 [holderlist.append(os.path.abspath(os.path.join(dir1,x))) for x in only_in_one] [holderlist.append(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: #遞歸子目錄 compareme(os.path.abspath(os.path.join(dir1,item)), os.path.abspath(os.path.join(dir2,item))) return holderlist def checkargv(): if len(sys.argv) < 2: #要求輸入源目錄與備份目錄 print ("Usage: ", sys.argv[0], "datadir backupdir") sys.exit() else: dir1 = sys.argv[1] dir2 = sys.argv[2] source_files = compareme(dir1,dir2) #對比源目錄與備份目錄 dir1 = os.path.abspath(dir1) if not dir2.endswith('/'): #備份目錄路徑加“/”符 dir2 = dir2+'/' dir2 = os.path.abspath(dir2) destination_files = [] createdir_bool = False for item in source_files: #遍歷返回的差異文件或目錄清單 destination_dir = re.sub(dir1,dir2,item) #將源目錄差異路徑清單對應替換成備份目錄 destination_files.append(destination_dir) if os.path.isdir(item): #如果差異路徑爲目錄且不存在,則再備份目錄中創建 if not os.path.exists(destination_dir): os.makedirs(destination_dir) createdir_bool = True #再次調用compareme函數標記 if createdir_bool: #重新調用compareme函數,重新遍歷新創建目錄的內容 destination_files = [] source_files = [] source_files = compareme(dir1,dir2) #調用compareme函數 for item in source_files: #獲取源目錄差異路徑清單,對應替換成備份目錄 destination_dir = re.sub(dir1,dir2,item) destination_files.append(destination_dir) print ("update item: ") print (source_files) #輸出更新項列表清單 copy_pair = zip(source_files,destination_files) #講源目錄與備份目錄文件清單拆分成元組 for item in copy_pair: if os.path.isfile(item[0]): #判斷是否爲文件,是則進行復制操作 shutil.copyfile(item[0], item[1]) if __name__ == '__main__': checkargv()
執行前:
[root@kurol pkg1]# tree -d test1 test2 test1 |-- test11 |-- test12 |-- test13 |-- test17 |-- test99 `-- testmmmm13 test2 |-- test11 |-- test12 |-- test13 |-- test14 `-- test17 11 directories
執行:
[root@kurol pkg1]# python3 checkdir2.py test1 test2 update item: ['/opt/python361/pkg1/test1/test99', '/opt/python361/pkg1/test1/testmmmm13']
執行後:
[root@kurol pkg1]# tree -d test1 test2 test1 |-- test11 |-- test12 |-- test13 |-- test17 |-- test99 `-- testmmmm13 test2 |-- test11 |-- test12 |-- test13 |-- test14 |-- test17 |-- test99 `-- testmmmm13 13 directories