文件與目錄差異對比方法
環境:
Python 2.6.6
linux系統
用到的模塊:filecmp
filecmp提供了:單文件對比,多文件對比,目錄對比
單文件對比:采用filecmp.cmp(f1,f2[,shallow])方法,比較文件名為f1和f2的文件的內容,相同返回True,不相同返回False,shallow默認是True,意思是只根據os.stat()方法返回的文件基本信息進行對比,比如最後訪問時間、修改時間、狀態改變時間等,會忽略文件內容的對比。當shallow為False時,則os.stat()與文件內容同時進行校驗。
例子:
>>> import filecmp >>> filecmp.cmp("/root/dir1/f1","/root/dir2/f1") True >>> filecmp.cmp("/root/dir1/f1","/root/dir2/f5") False
多文件對比:采用filecmp.cmpfiles(dir1, dir2, common[, shallow])方法,對比dir1與dir2目錄給定的文件清單。該方法返回文件名的三個列表,分別為匹配、不匹配、錯誤。匹配為包含匹配的文件的列表,不匹配反之,錯誤列表包括了目錄不存在文件、不具備讀權限或其他原因導致的不能比較的文件清單。
例子:
先建立一些文件:
代碼:
>>> filecmp.cmpfiles("/root/dir1","/root/dir2",[‘f1‘,‘f2‘,‘f3‘,‘f4‘,‘f5‘]) ([‘f1‘, ‘f2‘, ‘f3‘, ‘f4‘], [], [‘f5‘])
目錄對比:通過dircmp(a, b[, ignore[, hide]])類創建一個目錄比較對象,其中a和b是參加比較的目錄名。ignore代表文件名忽略的列表,並默認為[‘RCS‘, ‘CVS‘, ‘tags‘];hide代表隱藏的列表,默認為[os.curdir,os.pardir]。dircmp類可以獲得目錄比較的詳細信息,如只有在a目錄中包括的文件、a與b都存在的子目錄、匹配的文件等,同時支持遞歸。
例子:
#!/usr/bin/env python #-*—coding:utf-8-*- #2017,9,7 import filecmp a = "/root/dir1" #定義左目錄 b = "/root/dir2" #定義右目錄 dirobj = filecmp.dircmp(a,b,[‘1.py‘]) #目錄比較,忽略1.py文件。 dirobj.report() #比較當前指定目錄中的內容 dirobj.report_full_closure() #遞歸比較所有指定目錄的內容 dirobj.report_partial_closure() #比較當前指定目錄以及第一級目錄中的內容 print "_"*50 print "left_list:" + str(dirobj.left_list) #左目錄 print "_"*50 print "right_list:"+str(dirobj.right_list) #右目錄 print "_"*50 print "commom:"+str(dirobj.common) #兩邊共同存在的目錄 print "_"*50 print "left_only:"+str(dirobj.left_only) #只在左目錄中的文件或者目錄 print "_"*50 print "right_only:"+str(dirobj.right_only) #只在右目錄中的文件或者目錄 print "_"*50 print "common_dirs:"+str(dirobj.common_dirs)#兩邊目錄都存在的子目錄 print "_"*50 print "common_files:"+str(dirobj.common_files) #兩邊目錄都存在的文件 print "_"*50 print "common_funny:"+str(dirobj.common_funny) #兩邊目錄都存在的目錄 print "_"*50 print "same_files:"+str(dirobj.same_files) #匹配相同的文件 print "_"*50 print "diff_files:" + str(dirobj.diff_files) #不匹配的文件 print "_"*50 print "funny_files:" + str(dirobj.diff_files) #兩邊目錄中都存在,但是無法比較的文件
執行結果:
diff /root/dir1 /root/dir2 Only in /root/dir2 : [‘f5‘] Identical files : [‘f1‘, ‘f2‘, ‘f3‘, ‘f4‘] diff /root/dir1 /root/dir2 Only in /root/dir2 : [‘f5‘] Identical files : [‘f1‘, ‘f2‘, ‘f3‘, ‘f4‘] diff /root/dir1 /root/dir2 Only in /root/dir2 : [‘f5‘] Identical files : [‘f1‘, ‘f2‘, ‘f3‘, ‘f4‘] __________________________________________________ left_list:[‘f1‘, ‘f2‘, ‘f3‘, ‘f4‘] __________________________________________________ right_list:[‘f1‘, ‘f2‘, ‘f3‘, ‘f4‘, ‘f5‘] __________________________________________________ commom:[‘f1‘, ‘f2‘, ‘f3‘, ‘f4‘] __________________________________________________ left_only:[] __________________________________________________ right_only:[‘f5‘] __________________________________________________ common_dirs:[] __________________________________________________ common_files:[‘f1‘, ‘f2‘, ‘f3‘, ‘f4‘] __________________________________________________ common_funny:[] __________________________________________________ same_files:[‘f1‘, ‘f2‘, ‘f3‘, ‘f4‘] __________________________________________________ diff_files:[] __________________________________________________ funny_files:[]
實踐:效驗源與備份目錄差異
源代碼:
#!/usr/bin/env python #coding:utf-8 #2017,9,7 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 [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: return holderlist def main(): if len(sys.argv) > 2: dir1 = sys.argv[1] dir2 = sys.argv[2] else: print "usage:",sys.argv[0],"datadir backupdir" sys.exit() 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: destination_files = [] source_files=[] source_files=compareme(dir1,dir2) for item in source_files: destination_dir = re.sub(dir1,dir2,item) destination_files.append(destination_dir) print "updata 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__‘: main()
執行結果:
總結\註意\拓展:
總結:
本次學習不僅學會了文件備份的效驗,而且學習到了一個語法:
[holderlist.append(os.path.abspath(os.path.join(dir1,x))) for x in only_in_one] #正常寫法 for x in only_in_one: holderlist.append(os.path.abspath(os.path.join(dir1,x)))
註意:
在寫程序的時候一定要註意縮進,不然容易報錯,我在寫下面這句的時候就老報語法錯誤,做後讓別人打一遍,我復制一下才成功:
return holderlist
拓展:
re.sub是re模塊重要的組成部分,並且功能也非常強大,主要功能實現正則的替換
re.sub定義:
sub(pattern, repl, string, count=0, flags=0)
解釋:
pattern:為表示正則中的模式字符串,
repl為replacement,被替換的內容,repl可以是字符串,也可以是函數。
string為正則表達式匹配的內容。
count:由於正則表達式匹配到的結果是多個,使用count來限定替換的個數(順序為從左向右),默認值為0,替換所有的匹配到的結果。
flag是匹配模式,可以使用按位或’|’表示同時生效,也可以在正則表達式字符串中指定。
例子:
>>>import re >>>re.sub(r‘\w+‘,‘10‘,"ji 43 af,geq",2,flags=re.I) >>>‘10 10 af,geq‘
shutil模塊:
詳情參考:http://blog.csdn.net/xmnathan/article/details/36217631
參考鏈接1:https://book.2cto.com/201411/48243.html
參考鏈接2:http://blog.csdn.net/hjxzt1/article/details/73741507
參考資料1:百度知道
參考資料2:網絡資源
參考資料3:《Python自動化運維技術與最佳實踐》-劉天斯 著
本文出自 “天道酬勤” 博客,謝絕轉載!
文件與目錄差異對比方法