filecmp --- 文件及目錄的比較│Python標(biāo)準(zhǔn)庫(kù)

前情提示: 測(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è)文件是否相等

比較 f1f2 的文件袒哥,如果它們似乎相等則返回 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文件2os.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)注读宙。

參考資料

官方文檔

源代碼

python – filecmp.cmp()忽略不同的os.stat()簽名结闸?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末耻讽,一起剝皮案震驚了整個(gè)濱河市针肥,隨后出現(xiàn)的幾起案子具则,更是在濱河造成了極大的恐慌,老刑警劉巖匪凡,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稠通,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡玉控,警方通過(guò)查閱死者的電腦和手機(jī)奸远,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門耽梅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)诅迷,“玉大人众旗,你說(shuō)我怎么就攤上這事÷上耄” “怎么了技即?”我有些...
    開(kāi)封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵豹悬,是天一觀的道長(zhǎng)埃难。 經(jīng)常有香客問(wèn)我歼争,道長(zhǎng)贫途,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任待侵,我火速辦了婚禮丢早,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘秧倾。我一直安慰自己怨酝,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布那先。 她就那樣靜靜地躺著农猬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪售淡。 梳的紋絲不亂的頭發(fā)上斤葱,一...
    開(kāi)封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音揖闸,去河邊找鬼苦掘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛楔壤,可吹牛的內(nèi)容都是我干的鹤啡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蹲嚣,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼递瑰!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起隙畜,我...
    開(kāi)封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤抖部,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后议惰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體慎颗,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了俯萎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片傲宜。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖夫啊,靈堂內(nèi)的尸體忽然破棺而出函卒,到底是詐尸還是另有隱情,我是刑警寧澤撇眯,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布报嵌,位于F島的核電站,受9級(jí)特大地震影響熊榛,放射性物質(zhì)發(fā)生泄漏锚国。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一玄坦、第九天 我趴在偏房一處隱蔽的房頂上張望跷叉。 院中可真熱鬧,春花似錦营搅、人聲如沸云挟。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)园欣。三九已至,卻和暖如春休蟹,著一層夾襖步出監(jiān)牢的瞬間沸枯,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工赂弓, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绑榴,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓盈魁,卻偏偏與公主長(zhǎng)得像翔怎,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子杨耙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容