前情提示: 測(cè)試代碼中,右尖括號(hào)(>
)表示命令行中輸入的命令荐吵; 單獨(dú)一行并以井字符(#
)開(kāi)頭的為輸出內(nèi)容骑冗; 庫(kù)的導(dǎo)入僅在本文的第一個(gè)測(cè)試代碼中展現(xiàn),其他代碼塊均省略庫(kù)的導(dǎo)入代碼先煎。
-
系統(tǒng)類型:
Windows 10
-
python 版本:
Python 3.9.0
filecmp
模塊可以用于文件與文件之間或目錄與目錄之間的比較贼涩。并且可以通過(guò)設(shè)置參數(shù)來(lái)選取多種不同用時(shí)和不同準(zhǔn)確性的方案。
filecmp
模塊在進(jìn)行文件或目錄對(duì)比時(shí)薯蝎,最終僅能返回是否相等這一結(jié)果遥倦。某些場(chǎng)景需要更加詳細(xì)的結(jié)果說(shuō)明,可以使用 difflib
標(biāo)準(zhǔn)庫(kù)占锯。
快捷函數(shù)
filecmp.cmp(f1, f2, shallow=True)
參數(shù):
f1, f2: 要進(jìn)行比較的兩個(gè)文件
shallow: 關(guān)鍵字參數(shù), 參數(shù)值為布爾值, 默認(rèn)為 True;
如果為 True, 則判斷兩文件需要具有相同的 os.stat() 簽名才會(huì)認(rèn)為是相等的;
如果為 False, 則比較兩文件的內(nèi)容;
返回值:
布爾值, 兩個(gè)文件是否相等
比較 f1
和 f2
的文件袒哥,如果它們似乎相等則返回 True
,否則返回 False
消略。在官方文檔中用上了 '似乎' 一詞堡称,這讓人感覺(jué)有什么隱秘的信息文檔上沒(méi)有表達(dá)出來(lái)。
import filecmp
import os
'''本次測(cè)試代碼中存在 4 個(gè)待對(duì)比文件, 其中 文件1 與 文件2 內(nèi)容不同, 文件3 與 文件4 內(nèi)容相同'''
print(os.stat('文件1'))
print(os.stat('文件2'))
print(filecmp.cmp('文件1', '文件2', shallow=True))
print(filecmp.cmp('文件1', '文件2', shallow=False))
# os.stat_result(st_mode=33206, st_ino=1407374883609775, st_dev=3098197482, st_nlink=1, st_uid=0, st_gid=0, st_size=4, st_atime=1611109066, st_mtime=1611109066, st_ctime=1611043715)
# os.stat_result(st_mode=33206, st_ino=1688849860320432, st_dev=3098197482, st_nlink=1, st_uid=0, st_gid=0, st_size=4, st_atime=1611045689, st_mtime=1611045689, st_ctime=1611043722)
# True
# True
當(dāng)比較內(nèi)容相同的 文件1
與 文件2
時(shí)艺演,參數(shù) shallow
無(wú)論設(shè)置為 True
還是 False
結(jié)果都是 True
却紧。按照文檔所述,文件1
和 文件2
的 os.stat()
是不相同的胎撤,當(dāng)參數(shù) shallow
設(shè)置為 True
時(shí)晓殊,根據(jù)兩個(gè)文件的 os.stat()
最終應(yīng)該得到 False
。為什么實(shí)際運(yùn)行和文檔描述不同呢?
查閱一些資料后伤提,找到了一個(gè)比較合理的解釋巫俺,當(dāng)參數(shù) shallow
設(shè)置為 True
,那么 os.stat()
相同的會(huì)直接被視為相等肿男,當(dāng)兩個(gè)文件的 os.stat()
不同時(shí)识藤,依舊會(huì)對(duì)比文件中的內(nèi)容砚著。
另外,此函數(shù)會(huì)緩存比較結(jié)果痴昧,在下次比較時(shí)直接返回緩存結(jié)果稽穆。如果文件的 os.stat()
變化了,也就是文件被修改了赶撰,緩存自動(dòng)失效舌镶。緩存也能用下文中的 filecmp.clear_cache()
函數(shù)清除。
filecmp.cmpfiles(dir1, dir2, common, shallow=True)
參數(shù):
dir1, dir2: 目錄
common: 需要對(duì)比的文件名列表
shallow: 關(guān)鍵字參數(shù), 參數(shù)值為布爾值, 默認(rèn)為 True;
如果為 True, 則判斷兩文件需要具有相同的 os.stat() 簽名才會(huì)認(rèn)為是相等的;
如果為 False, 則比較兩文件的內(nèi)容;
返回值:
元組, 包含三個(gè)類型為列表的元素.
比較兩個(gè)目錄下的指定文件豪娜,返回對(duì)比結(jié)果餐胀,返回值是包含三個(gè)類型為列表的元素的元組。
'''
文件目錄如下, 其中, 兩個(gè)目錄內(nèi)的 文件a 內(nèi)容相同, 文件c 內(nèi)容不同
- 目錄1
- 文件a
- 目錄b
- 文件c
- 文件d
- 目錄2
- 文件a
- 目錄b
- 文件c
'''
'''對(duì)比兩目錄下的文件'''
print(filecmp.cmpfiles('目錄1', '目錄2', ['文件a', '目錄b/文件c', '文件d']))
# (['文件a'], ['目錄b/文件c'], ['文件d'])
參數(shù) common
列舉要對(duì)比的文件名瘤载,分別對(duì)比兩個(gè)目錄下的同名文件否灾,如果兩個(gè)文件相同,則加入返回值的第一個(gè)元素內(nèi); 如果兩個(gè)文件內(nèi)容不同鸣奔,則加入返回值的第二個(gè)元素內(nèi); 如果文件無(wú)權(quán)限讀取或者文件在任一目錄內(nèi)缺失墨技,則加入返回值的第三個(gè)元素內(nèi);
參數(shù) shallow
與上文中 filecmp.cmp()
函數(shù)意義相同。
filecmp.clear_cache()
清除 filecmp
緩存挎狸。一般情況下扣汪,文件修改后,文件的 os.stat()
自然會(huì)改變锨匆,緩存也會(huì)自動(dòng)失效崭别。但是如果文件被過(guò)快的修改,以至于超過(guò)底層文件系統(tǒng)記錄修改時(shí)間的精度時(shí)恐锣,那么此后的文件對(duì)比將可能會(huì)出現(xiàn)問(wèn)題茅主,此函數(shù)就是為了解決這個(gè)問(wèn)題。
但是土榴,這種文件過(guò)快的修改不知道怎樣測(cè)試出來(lái)? 大家有知道的嗎?
dircmp 類
class filecmp.dircmp(a, b, ignore=None, hide=None)
參數(shù):
a, b: 目錄
ignore: 關(guān)鍵字參數(shù), 需要忽略的文件名列表, 默認(rèn)為 filecmp.DEFAULT_IGNORES
hide: 關(guān)鍵字參數(shù), 需要隱藏的文件名列表, 默認(rèn)為 [os.curdir, os.pardir]
創(chuàng)建一個(gè)用于比較兩個(gè)目錄的目錄比較對(duì)象诀姚。參數(shù) ignore
可忽略指定的文件名,hide
可隱藏指定的文件名鞭衩。
print(filecmp.DEFAULT_IGNORES)
# ['RCS', 'CVS', 'tags', '.git', '.hg', '.bzr', '_darcs', '__pycache__']
print(os.curdir)
# .
print(os.pardir)
# ..
dircmp
類中有許多屬性学搜,這里使用測(cè)試代碼直接展示:
dircmp_test = filecmp.dircmp('目錄1', '目錄2')
'''第一個(gè)(相對(duì)左邊)參數(shù), 也是第一個(gè)目錄的名稱'''
print(dircmp_test.left)
# 目錄1
'''第二個(gè)(相對(duì)右邊)參數(shù), 也是第二個(gè)目錄的名稱'''
print(dircmp_test.right)
# 目錄2
'''經(jīng)參數(shù) hide 與參數(shù) ignore 過(guò)濾后, 第一個(gè)目錄內(nèi)的所有文件與子目錄'''
print(dircmp_test.left_list)
# ['文件a', '文件d', '目錄b']
'''經(jīng)參數(shù) hide 與參數(shù) ignore 過(guò)濾后, 第二個(gè)目錄內(nèi)的所有文件與子目錄'''
print(dircmp_test.right_list)
# ['文件a', '目錄b']
'''同時(shí)存在兩個(gè)目錄下的文件與子目錄'''
print(dircmp_test.common)
# ['文件a', '目錄b']
'''僅存在第一個(gè)目錄下的文件與子目錄'''
print(dircmp_test.left_only)
# ['文件d']
'''僅存在第二個(gè)目錄下的文件與子目錄'''
print(dircmp_test.right_only)
# []
'''同時(shí)存在兩個(gè)目錄下的子目錄'''
print(dircmp_test.common_dirs)
# ['目錄b']
'''將 common_dirs 屬性值映射為 dircmp 對(duì)象的字典'''
print(dircmp_test.subdirs)
# {'目錄b': <filecmp.dircmp object at 0x000002A9A1374F70>}
'''同時(shí)存在兩個(gè)目錄下的文件'''
print(dircmp_test.common_files)
# ['文件a']
'''在兩個(gè)目錄中類型不同的名字论衍,或者那些 os.stat() 報(bào)告錯(cuò)誤的名字'''
print(dircmp_test.common_funny)
# []
'''在兩個(gè)目錄下, 使用類的比較操作符相同的文件'''
print(dircmp_test.same_files)
# ['文件a']
'''在兩個(gè)目錄下, 使用類的比較操作符不同的文件'''
print(dircmp_test.diff_files)
# []
'''無(wú)法比較的文件'''
print(dircmp_test.funny_files)
# []
dircmp
類也提供了一些用于打印信息的方法,同樣蜒蕾,直接在測(cè)試用例中展示:
'''將 a 與 b 之間的比較打印'''
dircmp_test.report()
# diff 目錄1 目錄2
# Only in 目錄1 : ['文件d']
# Identical files : ['文件a']
# Common subdirectories : ['目錄b']
'''打印 a 與 b 及共同直接子目錄的比較結(jié)果'''
dircmp_test.report_partial_closure()
# diff 目錄1 目錄2
# Only in 目錄1 : ['文件d']
# Identical files : ['文件a']
# Common subdirectories : ['目錄b']
#
# diff 目錄1\目錄b 目錄2\目錄b
# Differing files : ['文件c']
'''打印 a 與 b 及共同子目錄比較結(jié)果(遞歸地)'''
dircmp_test.report_full_closure()
# diff 目錄1 目錄2
# Only in 目錄1 : ['文件d']
# Identical files : ['文件a']
# Common subdirectories : ['目錄b']
#
# diff 目錄1\目錄b 目錄2\目錄b
# Differing files : ['文件c']
公眾號(hào) : 「python雜貨鋪」,專注于 python 語(yǔ)言及其相關(guān)知識(shí)毅桃。發(fā)掘更多原創(chuàng)文章钥飞,期待您的關(guān)注读宙。