1. 程式人生 > >Python自動化運維筆記(五):使用filecmp模組實現檔案以及檔案目錄差異對比

Python自動化運維筆記(五):使用filecmp模組實現檔案以及檔案目錄差異對比

執行環境:Python3.6Windwos10 RS1Pycharm
參考書籍—《Python自動化運維--技術與最佳實踐》劉天斯著

模組介紹

Python2.3以上的版本預設自帶了filecmp模組,無需額外安裝。我們可以用這個模組來檢查原式與目標檔案的一致性,filecmp可以實現檔案、目錄、遍歷子目錄的差異對比功能。

模組使用

filecmp提供了三個操作方法。

  • cmp:單檔案對比
  • cmpfiles:多檔案對比
  • dircmp:目錄對比

單檔案對比

使用的是filecmp.cmp(f1,f2[,shallow])

。其中f1f2為檔案,當兩個檔案相同時返回True,不同返回False,(shallow預設為True,其意思是隻根據os.stat()方法返回的檔案基本資訊進行對比[最後訪問時間、修改時間、狀態改變時間等,而不考慮檔案內容])。當shallowFalse時,則os.stat()與檔案內容同時進行校驗。
現在我在我程式碼的當前路徑下有三個分別名為File1.txtFile2.txtFile3.txt的檔案,File1.txtFile3.txt兩個檔案是單獨建立的文字檔案,而File2.txtFile1.txt的副本檔案,即直接由複製檔案File1.txt並改名File2.txt得到。
所以按理來說File1.txtFile2.txt兩個檔案完全相同、而與File3.txt檔案不同。
下面使用程式碼進行驗證:

Python 3.6.2 (v3.6.2:5fd33b5, Jul  8 2017, 04:14:34) [MSC v.1900 32 bit (Intel)] on win32
>>> import filecmp
>>> filecmp.cmp('./File1.txt', './File2.txt')
True        # 說明兩個檔案相同,返回True
>>> filecmp.cmp('./File1.txt'
, './File3.txt') False # 說明兩個檔案不同,返回False

多檔案對比

比較兩個資料夾內指定檔案是否相等。引數dir1, dir2指定要比較的資料夾,引數common指定要比較的檔名列表。函式返回包含3個list元素的元組,分別表示匹配、不匹配以及錯誤的檔案列表。錯誤的檔案指的是不存在的檔案,或檔案被瑣定不可讀,或沒許可權讀檔案,或者由於其他原因訪問不了該檔案。

# 下列檔案是dir1資料夾下所有檔案的MD5值
FBAAF8CC3C1DF70B183CB8E8FBDFC57C *File1.txt
FBAAF8CC3C1DF70B183CB8E8FBDFC57C *File2.txt
16EC37C499F64FC60E95650B500E30A4 *File3.txt
202CB962AC59075B964B07152D234B70 *File4.txt

# 下列檔案是dir1資料夾下所有檔案的MD5值
FBAAF8CC3C1DF70B183CB8E8FBDFC57C *File1.txt
FBAAF8CC3C1DF70B183CB8E8FBDFC57C *File2.txt
D41D8CD98F00B204E9800998ECF8427E *File3.txt
CB30FC9CEC9A2D04EF49B22E2066C264 *File5.txt

# 根據MD5值可以知道,兩個資料夾下的File1.txt、File2.txt相匹配,
# 而File3.txt不匹配,
# 另外對於File4.txt和File5.txt兩個檔案只在各自的目錄下存在。

使用示例程式碼驗證:

>>> filecmp.cmpfiles('./dir1', './dir2', ['File1.txt', 'File2.txt', 'File3.txt', 'File4.txt', 'File5.txt'])
(['File1.txt', 'File2.txt'], ['File3.txt'], ['File4.txt', 'File5.txt'])       # 返回為列表
# 列表[0] == 匹配
# 列表[1] == 不匹配
# 列表[2] == 不存在,無法比較

目錄對比

目錄對比,通過filecmp(a,b[,ignore[,hide]])類建立一個目錄比較物件用於比較資料夾,通過該類比較兩個資料夾,可以獲取一些詳細的比較結果(如只在A資料夾存在的檔案列表),並支援子資料夾的遞迴比較。

dircmp提供了三個方法用於報告比較的結果:

  • report():只比較指定資料夾中的內容(檔案與資料夾)
  • report_partial_closure():比較資料夾及第一級子資料夾的內容
  • report_full_closure():遞迴比較所有的資料夾的內容

另外為了輸出更加詳細的資訊,dircmp類還提供了以下屬性:

  • left_list:左邊資料夾中的檔案與資料夾列表;
  • right_list:右邊資料夾中的檔案與資料夾列表;
  • common:兩邊資料夾中都存在的檔案或資料夾;
  • left_only:只在左邊資料夾中存在的檔案或資料夾;
  • right_only:只在右邊資料夾中存在的檔案或資料夾;
  • common_dirs:兩邊資料夾都存在的子資料夾;
  • common_files:兩邊資料夾都存在的子檔案;
  • common_funny:兩邊資料夾都存在的子資料夾;
  • same_files:匹配的檔案;
  • diff_files:不匹配的檔案;
  • funny_files:兩邊資料夾中都存在,但無法比較的檔案;
  • subdirs:將common_dirs 目錄對映到新的dircmp物件,格式為字典的型別。

示例程式碼,比較dir1dir2資料夾目錄的差異

# -*- coding: utf-8 -*-

import filecmp

a = "./dir1"  # 定義左目錄
b = "./dir2"  # 定義右目錄

dirobj = filecmp.dircmp(a, b, ['EXT.txt'])  # 目錄比較,忽略EXT.txt檔案

# 輸出對比結果資料報表,詳細說明請參考filecmp類方法及屬性資訊
dirobj.report()
dirobj.report_partial_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))

執行結果下:

C:\Users\imwoo\AppData\Local\Programs\Python\Python36-32\python.exe E:/Python_Test/Code/Auto_Operations/filecmpTest.py
diff ./dir1 ./dir2
Only in ./dir1 : ['File4.txt']
Only in ./dir2 : ['File5.txt']
Identical files : ['File1.txt', 'File2.txt']
Differing files : ['File3.txt']
diff ./dir1 ./dir2
Only in ./dir1 : ['File4.txt']
Only in ./dir2 : ['File5.txt']
Identical files : ['File1.txt', 'File2.txt']
Differing files : ['File3.txt']
diff ./dir1 ./dir2
Only in ./dir1 : ['File4.txt']
Only in ./dir2 : ['File5.txt']
Identical files : ['File1.txt', 'File2.txt']
Differing files : ['File3.txt']
left_list:['File1.txt', 'File2.txt', 'File3.txt', 'File4.txt']
right_list:['File1.txt', 'File2.txt', 'File3.txt', 'File5.txt']
common:['File1.txt', 'File2.txt', 'File3.txt']
left_only:['File4.txt']
right_only:['File5.txt']
common_dirs:[]
common_files:['File1.txt', 'File2.txt', 'File3.txt']
common_funny:[]
same_file:['File1.txt', 'File2.txt']
diff_files:['File3.txt']
funny_files:[]

其實個人覺得上面的資訊不太方便理解,所以附上我的一張目錄tree圖:

├─dir1
│      EXT.txt
│      File1.txt
│      File2.txt
│      File3.txt
│      File4.txt
│
├─dir2
│      EXT.txt
│      File1.txt
│      File2.txt
│      File3.txt
│      File5.txt
│
└─__pycache__