如何在Python中比較檔案


問題。

你需要在Python中比較檔案。

解決方案。

Python中的`filecmp`模組可以用來比較檔案和目錄。1.

cmp(file1, file2[, shallow])

`filecmp.cmp()` 比較檔案`file1`和`file2`,如果相同則返回`True`,否則返回`False`。預設情況下,具有`os.stat()`返回的相同屬性的檔案被認為是相等的。如果未提供`shallow`引數(或為`True`),則具有相同stat簽名的檔案被認為是相等的。

cmpfiles(dir1, dir2, common[, shallow])

`filecmp.cmpfiles()` 比較兩個目錄`dir1`和`dir2`中`common`列表中包含的檔案的內容。`cmpfiles`返回一個包含三個列表的元組 - `match`、`mismatch`、`errors`檔名。

  • `match` - 列出在兩個目錄中都相同的檔案。

  • `mismatch` - 列出不匹配的檔案。

  • `errors` - 列出由於某種原因無法比較的檔案。

dircmp(dir1, dir2 [, ignore[, hide]])

`filecmp.dircmp()` 建立一個目錄比較物件,可用於對目錄`dir1`和`dir2`執行各種比較操作。

  • `ignore` - 忽略要忽略的檔名列表,預設值為['RCS','CVS','tags']。

  • `hide` - 要隱藏的檔名列表,預設為[os.curdir, os.pardir](在UNIX上為['.', '..'])。

`filecmp.dircmp`的例項實現了以下方法,這些方法將詳細的報告列印到`sys.stdout`

  • `report()`:列印兩個目錄之間的比較。

  • `report_partial_closure()`:列印兩個目錄以及兩個`目錄`的直接子目錄的比較。

  • `report_full_closure()`:列印兩個目錄、所有子目錄、`這些子目錄`的所有子目錄等的比較(即遞迴)。

  • `left_list`:在目錄路徑1中找到的檔案和子目錄,不包括`hidelist`中的元素。

  • `right_list`:在目錄路徑2中找到的檔案和子目錄,不包括`hidelist`中的元素。

  • `common`:同時存在於目錄路徑1和目錄路徑2中的檔案和子目錄。

  • `left_only`:僅存在於目錄路徑1中的檔案和子目錄。

  • `right_only`:僅存在於目錄路徑2中的檔案和子目錄。

  • `common_dirs`:同時存在於目錄路徑1和目錄路徑2中的子目錄。

  • `common_files`:同時存在於目錄路徑1和目錄路徑2中的檔案。

  • `same_files`:內容在目錄路徑1和目錄路徑2中都相同的檔案的路徑。

  • `diff_files`:同時存在於目錄路徑1和目錄路徑2中,但內容不同的檔案的路徑。

  • `funny_files`:同時存在於目錄路徑1和目錄路徑2中,但由於某種原因無法比較的檔案的路徑。

  • `subdirs`:一個字典,將`common_dirs`中的名稱對映到`dircmp`物件。

準備用於比較的測試資料。

import os
# prepare test data
def makefile(filename,text=None):
"""
Function: make some files
params : input file, body
"""

with open(filename, 'w') as f:
f.write(text or filename)

return

# prepare test data
def makedirectory(directory_name):
"""
Function: make directories
params : input directory
"""
if not os.path.exists(directory_name):
os.mkdir(directory_name)


# Get current working directory
present_directory = os.getcwd()

# change to directory provided
os.chdir(directory_name)

# Make two directories
os.mkdir('dir1')
os.mkdir('dir2')

# Make two same subdirectories
os.mkdir('dir1/common_dir')
os.mkdir('dir2/common_dir')

# Make two different subdirectories
os.mkdir('dir1/dir_only_in_dir1')
os.mkdir('dir2/dir_only_in_dir2')

# Make a unqiue file one each in directory
makefile('dir1/file_only_in_dir1')
makefile('dir2/file_only_in_dir2')

# Make a unqiue file one each in directory
makefile('dir1/common_file', 'Hello, Writing Same Content')
makefile('dir2/common_file', 'Hello, Writing Same Content')

# Make a non unqiue file one each in directory
makefile('dir1/not_the_same')
makefile('dir2/not_the_same')

makefile('dir1/file_in_dir1', 'This is a file in dir1')

os.mkdir('dir2/file_in_dir1')

os.chdir(present_directory)

return

if __name__ == '__main__':
os.chdir(os.getcwd())
makedirectory('example')
makedirectory('example/dir1/common_dir')
makedirectory('example/dir2/common_dir')
  • **filecmp示例** 執行filecmp示例。`shallow`引數告訴`cmp()`是否除了元資料之外還要檢視檔案的內容。

預設情況下,使用`os.stat()`提供的可用資訊執行淺比較。如果結果相同,則認為檔案相同。因此,即使內容不同,大小相同且建立時間相同的也會被報告為相同。

當`shallow`為`False`時,總是比較檔案的內容。

import filecmp

print('Output \n *** Common File :', end=' ')

print(filecmp.cmp('example/dir1/common_file',
'example/dir2/common_file'), end=' ')

print(filecmp.cmp('example/dir1/common_file',
'example/dir2/common_file', shallow=False))

print(' *** Different Files :', end=' ')

print(filecmp.cmp('example/dir1/not_the_same',
'example/dir2/not_the_same'), end=' ')

print(filecmp.cmp('example/dir1/not_the_same',
'example/dir2/not_the_same', shallow=False))

print(' *** Identical Files :', end=' ')

print(filecmp.cmp('example/dir1/file_only_in_dir1',
'example/dir1/file_only_in_dir1'), end=' ')

print(filecmp.cmp('example/dir1/file_only_in_dir1',
'example/dir1/file_only_in_dir1', shallow=False))

輸出

*** Common File : True True
*** Different Files : False False
*** Identical Files : True True
  • `cmpfiles`示例

使用`cmpfiles()`比較兩個目錄中的一組檔案,而不遞迴。

import filecmp

import os

# Determine the items that exist in both directories.
dir1_contents = set(os.listdir('example/dir1'))
dir2_contents = set(os.listdir('example/dir2'))
common = list(dir1_contents & dir2_contents)

common_files = [f for f in common if os.path.isfile(os.path.join('example/dir1', f))]

print(f' *** Common files are : {common_files}')

# Now, let us compare the directories
match, mismatch, errors = filecmp.cmpfiles(
'example/dir1',
'example/dir2',
common_files,)

print(f' *** Matched files are : {match}')
print(f' *** mismatch files are : {mismatch}')
print(f' *** errors files are : {errors}')
*** Common files are : ['file_in_dir1', 'not_the_same', 'common_file']
*** Matched files are : ['common_file']
*** mismatch files are : ['file_in_dir1', 'not_the_same']
*** errors files are : []

7. 比較目錄。

import filecmp
dc = filecmp.dircmp('example/dir1', 'example/dir2')
print(f"output \n *** Printing detaile report: \n ")
print(dc.report())
print(f"\n")
print(dc.report_full_closure())

輸出

*** Printing detaile report:

diff example/dir1 example/dir2
Only in example/dir1 : ['dir_only_in_dir1', 'file_only_in_dir1']
Only in example/dir2 : ['dir_only_in_dir2', 'file_only_in_dir2']
Identical files : ['common_file']
Differing files : ['not_the_same']
Common subdirectories : ['common_dir']
Common funny cases : ['file_in_dir1']
None

diff example/dir1 example/dir2
Only in example/dir1 : ['dir_only_in_dir1', 'file_only_in_dir1']
Only in example/dir2 : ['dir_only_in_dir2', 'file_only_in_dir2']
Identical files : ['common_file']
Differing files : ['not_the_same']
Common subdirectories : ['common_dir']
Common funny cases : ['file_in_dir1']

diff example/dir1\common_dir example/dir2\common_dir
Common subdirectories : ['dir1', 'dir2']

diff example/dir1\common_dir\dir1 example/dir2\common_dir\dir1
Identical files : ['common_file', 'file_in_dir1', 'file_only_in_dir1', 'not_the_same']
Common subdirectories : ['common_dir', 'dir_only_in_dir1']

diff example/dir1\common_dir\dir1\common_dir example/dir2\common_dir\dir1\common_dir

diff example/dir1\common_dir\dir1\dir_only_in_dir1 example/dir2\common_dir\dir1\dir_only_in_dir1

diff example/dir1\common_dir\dir2 example/dir2\common_dir\dir2
Identical files : ['common_file', 'file_only_in_dir2', 'not_the_same']
Common subdirectories : ['common_dir', 'dir_only_in_dir2', 'file_in_dir1']

diff example/dir1\common_dir\dir2\common_dir example/dir2\common_dir\dir2\common_dir

diff example/dir1\common_dir\dir2\dir_only_in_dir2 example/dir2\common_dir\dir2\dir_only_in_dir2

diff example/dir1\common_dir\dir2\file_in_dir1 example/dir2\common_dir\dir2\file_in_dir1
None

您可以進一步嘗試要點1中提到的所有命令,以檢視每種方法的行為。

更新於:2020年11月9日

8K+ 瀏覽量

啟動你的職業生涯

完成課程後獲得認證

開始學習
廣告
© . All rights reserved.