1. 程式人生 > >python筆記系列:檔案內容、檔案及資料夾的對比difflib、filecmp

python筆記系列:檔案內容、檔案及資料夾的對比difflib、filecmp

檔案內容對比#!/usr/bin/pythonimport difflibtext1 = """text1:This module provides classes and functions for comparing sequences.including HTML and context and unified diffs.difflib document v7.4add string"""text1_lines = text1.splitlines()text2 = """text2:This module provides classes and functions for Comparing sequences.including HTML and context and unified diffs.difflib document v7.5"""text2_lines = text2.splitlines()d = difflib.Differ()diff = d.compare(text1_lines, text2_lines)print '\n'.join(list(diff))對比符號含義說明‘-’ 第一個序列有,第二個無‘+’ 第一個序列無,第二個有‘ ’ 兩個一致‘?’ 兩序列存在增量差異'^' 標誌出兩序列的差異字元採用HtmlDiff()類的make_file()方法可生成美觀的HTML文件上述示例的以下部分d = difflib.Differ()diff = d.compare(text1_lines, text2_lines)print '\n'.join(list(diff))替換為d = difflib.HtmlDiff()print d.make_file(text1_lines, text2_lines)檔案命名為simple2.py,執行 python simple2.py > diff.html,可生成對比檔案Nginx配置檔案對比
#!/usr/bin/python# coding=UTF-8import difflibimport systry: textfile1=sys.argv[1] #第一個檔案路徑引數 textfile2=sys.argv[2] #第二個檔案路徑引數except Exception,e: print "Error:"+str(e) print "Usage: simple3.py filename1 filename2" sys.exit()def readfile(filename): try: fileHandle = open (filename, 'rb' ) text=fileHandle.read().splitlines() fileHandle.close() return text except IOError as error: print('Read file Error:'+str(error)) sys.exit()if textfile1=="" or textfile2=="": print "Usage: simple3.py filename1 filename2" sys.exit()text1_lines = readfile(textfile1) text2_lines = readfile(textfile2) d = difflib.HtmlDiff()print d.make_file(text1_lines, text2_lines)檔案執行:python simple3.py nginx.conf.v1 nginx.conf.v2 > diff.html檔案與目錄差異對比
filecmp模組的三個操作方法cmp 單檔案對比cmpfiles 多檔案對比dircmp 目錄對比filecmp.cmp(f1,f2[,shallow]) 對比檔案f1、f2,相同返回True,否則False,shallow預設為True,只根據os.stat()方法返回的檔案基本資訊對比,如最後訪問時間、修改時間、狀態改變時間等shallow為False時,則os.stat()、檔案內容同時進行校驗>>> import filecmp>>> filecmp.cmp("/root/test/a","/root/test/b")False>>> filecmp.cmp("/root/test/a","/root/test/a")Truefilecmp.cmpfiles(dir1,dir2,common[,shallow]),該方法返回檔名的三個列表,分別為匹配、不匹配、錯誤,錯誤列表包括目錄不存在檔案、不具備讀寫許可權或其他原因導致的不能比較的檔案清單>>>filecmp.cmpfiles("/root/test/dir1","/root/test/dir2",['f1','f2','f3','f4','f5'])(['f1','f2'],['f3'],['f4','f5'])filecmp.dircmp(a,b[,ignore[,hide]]) ignore代表檔名忽略的列表,預設為['RCS','CVS','tags']hide代表隱藏的列表,預設為[os.curdir,os.pardir]dircmp支援遞迴,提供三個輸出報告的方法:report() #比較目錄中的內容report_partial_closure() #比較目錄及其第一級子目錄中的內容report_full_closure() #遞迴比較所有指定目錄的內容dircmp類提供一下屬性:left 左目錄right 右目錄left_list 左目錄中的檔案及目錄right_list 右目錄中的檔案及目錄common 左右共有的檔案及目錄left_only 只在左目錄有的檔案或目錄right_only 只在右目錄有的檔案或目錄common_dirs 兩邊都有的子目錄common_files 兩邊都有的子檔案common_funny 兩邊都有的子目錄(不同目錄型別或os.stat()記錄的錯誤)same_files 匹配相同的檔案diff_files 不匹配的檔案funny_files 兩邊都有但無法比較的檔案subdirs 將common_dirs目錄名對映到新的dircmp物件,格式為字典型別通過dircmp()實現目錄差異對比,同時輸出目錄對比物件所有屬性資訊
import filecmpa="/home/test/filecmp/dir1"b="/home/test/filecmp/dir2"dirobj=filecmp.dircmp(a,b,['test.py']) #ignore test.pyprint "-------------------report---------------------"dirobj.report()print "-------------report_partial_closure-----------"dirobj.report_partial_closure()print "-------------report_full_closure--------------"dirobj.report_full_closure()print "left_list:"+ str(dirobj.left_list)print "right_list:"+ str(dirobj.right_list)print "common:"+ str(dirobj.common)print "left_only:"+ str(dirobj.left_only)print "right_only:"+ str(dirobj.right_only)print "common_dirs:"+ str(dirobj.common_dirs)print "common_files:"+ str(dirobj.common_files)print "common_funny:"+ str(dirobj.common_funny)print "same_file:"+ str(dirobj.same_files)print "diff_files:"+ str(dirobj.diff_files)print "funny_files:"+ str(dirobj.funny_files)校驗源與備份目錄差異,並增量備份使用filecmp模組的left_only、diff_files 遞迴獲取源目錄的更新項,再通過shutil.copyfile、os.makedirs方法對更新項進行復制,最終保持一致狀態#!/usr/bin/env python# coding=UTF-8import os, sysimport filecmpimport reimport shutilholderlist=[]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: #遞迴子目錄 compareme(os.path.abspath(os.path.join(dir1,item)), \ os.path.abspath(os.path.join(dir2,item))) #“\”為換行連線符 #return holderlist #原始碼 return holderlist #修正後,未對齊該函式可能返回none,導致程式報錯#注意程式碼對齊,空格和tab不能混用!!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: #重新呼叫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__': main()檔案內容對比#!/usr/bin/pythonimport difflibtext1 = """text1:This module provides classes and functions for comparing sequences.including HTML and context and unified diffs.difflib document v7.4add string"""text1_lines = text1.splitlines()text2 = """text2:This module provides classes and functions for Comparing sequences.including HTML and context and unified diffs.difflib document v7.5"""text2_lines = text2.splitlines()d = difflib.Differ()diff = d.compare(text1_lines, text2_lines)print '\n'.join(list(diff))對比符號含義說明‘-’ 第一個序列有,第二個無‘+’ 第一個序列無,第二個有‘ ’ 兩個一致‘?’ 兩序列存在增量差異'^' 標誌出兩序列的差異字元採用HtmlDiff()類的make_file()方法可生成美觀的HTML文件上述示例的以下部分d = difflib.Differ()diff = d.compare(text1_lines, text2_lines)print '\n'.join(list(diff))替換為d = difflib.HtmlDiff()print d.make_file(text1_lines, text2_lines)檔案命名為simple2.py,執行 python simple2.py > diff.html,可生成對比檔案Nginx配置檔案對比#!/usr/bin/python# coding=UTF-8import difflibimport systry: textfile1=sys.argv[1] #第一個檔案路徑引數 textfile2=sys.argv[2] #第二個檔案路徑引數except Exception,e: print "Error:"+str(e) print "Usage: simple3.py filename1 filename2" sys.exit()def readfile(filename): try: fileHandle = open (filename, 'rb' ) text=fileHandle.read().splitlines() fileHandle.close() return text except IOError as error: print('Read file Error:'+str(error)) sys.exit()if textfile1=="" or textfile2=="": print "Usage: simple3.py filename1 filename2" sys.exit()text1_lines = readfile(textfile1) text2_lines = readfile(textfile2) d = difflib.HtmlDiff()print d.make_file(text1_lines, text2_lines)檔案執行:python simple3.py nginx.conf.v1 nginx.conf.v2 > diff.html檔案與目錄差異對比filecmp模組的三個操作方法cmp 單檔案對比cmpfiles 多檔案對比dircmp 目錄對比filecmp.cmp(f1,f2[,shallow]) 對比檔案f1、f2,相同返回True,否則False,shallow預設為True,只根據os.stat()方法返回的檔案基本資訊對比,如最後訪問時間、修改時間、狀態改變時間等shallow為False時,則os.stat()、檔案內容同時進行校驗>>> import filecmp>>> filecmp.cmp("/root/test/a","/root/test/b")False>>> filecmp.cmp("/root/test/a","/root/test/a")Truefilecmp.cmpfiles(dir1,dir2,common[,shallow]),該方法返回檔名的三個列表,分別為匹配、不匹配、錯誤,錯誤列表包括目錄不存在檔案、不具備讀寫許可權或其他原因導致的不能比較的檔案清單>>>filecmp.cmpfiles("/root/test/dir1","/root/test/dir2",['f1','f2','f3','f4','f5'])(['f1','f2'],['f3'],['f4','f5'])filecmp.dircmp(a,b[,ignore[,hide]]) ignore代表檔名忽略的列表,預設為['RCS','CVS','tags']hide代表隱藏的列表,預設為[os.curdir,os.pardir]dircmp支援遞迴,提供三個輸出報告的方法:report() #比較目錄中的內容report_partial_closure() #比較目錄及其第一級子目錄中的內容report_full_closure() #遞迴比較所有指定目錄的內容dircmp類提供一下屬性:left 左目錄right 右目錄left_list 左目錄中的檔案及目錄right_list 右目錄中的檔案及目錄common 左右共有的檔案及目錄left_only 只在左目錄有的檔案或目錄right_only 只在右目錄有的檔案或目錄common_dirs 兩邊都有的子目錄common_files 兩邊都有的子檔案common_funny 兩邊都有的子目錄(不同目錄型別或os.stat()記錄的錯誤)same_files 匹配相同的檔案diff_files 不匹配的檔案funny_files 兩邊都有但無法比較的檔案subdirs 將common_dirs目錄名對映到新的dircmp物件,格式為字典型別通過dircmp()實現目錄差異對比,同時輸出目錄對比物件所有屬性資訊import filecmpa="/home/test/filecmp/dir1"b="/home/test/filecmp/dir2"dirobj=filecmp.dircmp(a,b,['test.py']) #ignore test.pyprint "-------------------report---------------------"dirobj.report()print "-------------report_partial_closure-----------"dirobj.report_partial_closure()print "-------------report_full_closure--------------"dirobj.report_full_closure()print "left_list:"+ str(dirobj.left_list)print "right_list:"+ str(dirobj.right_list)print "common:"+ str(dirobj.common)print "left_only:"+ str(dirobj.left_only)print "right_only:"+ str(dirobj.right_only)print "common_dirs:"+ str(dirobj.common_dirs)print "common_files:"+ str(dirobj.common_files)print "common_funny:"+ str(dirobj.common_funny)print "same_file:"+ str(dirobj.same_files)print "diff_files:"+ str(dirobj.diff_files)print "funny_files:"+ str(dirobj.funny_files)校驗源與備份目錄差異,並增量備份使用filecmp模組的left_only、diff_files 遞迴獲取源目錄的更新項,再通過shutil.copyfile、os.makedirs方法對更新項進行復制,最終保持一致狀態#!/usr/bin/env python# coding=UTF-8import os, sysimport filecmpimport reimport shutilholderlist=[]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: #遞迴子目錄 compareme(os.path.abspath(os.path.join(dir1,item)), \ os.path.abspath(os.path.join(dir2,item))) #“\”為換行連線符 #return holderlist #原始碼 return holderlist #修正後,未對齊該函式可能返回none,導致程式報錯#注意程式碼對齊,空格和tab不能混用!!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: #重新呼叫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__': main()