Vấn đề
Bạn cần so sánh hai file hoặc hai thư mục trong Python.
Giải pháp
Module filecmp trong Python dùng để so sánh file và thư mục.
Các hàm chính
1. cmp(file1, file2[, shallow])
So sánh hai file file1 và file2, trả về True nếu giống nhau, False nếu khác. Mặc định so sánh "nông" (shallow=True) dựa trên metadata từ os.stat() (kích thước, thời gian tạo...). Nếu shallow=False, so sánh nội dung file.
2. cmpfiles(dir1, dir2, common[, shallow])
So sánh nội dung các file trong danh sách common nằm trong hai thư mục dir1 và dir2. Trả về tuple 3 danh sách: match, mismatch, errors.
match: file giống nhau ở cả hai thư mục.mismatch: file khác nhau.errors: file không thể so sánh (lỗi quyền, v.v.).
3. dircmp(dir1, dir2[, ignore[, hide]])
Tạo đối tượng so sánh thư mục để thực hiện các phép so sánh chi tiết.
ignore: danh sách tên file bỏ qua (mặc định:['RCS', 'CVS', 'tags']).hide: danh sách tên file ẩn (mặc định:[os.curdir, os.pardir]tức['.', '..']trên UNIX).
Đối tượng dircmp có các phương thức in báo cáo ra sys.stdout:
report(): In so sánh hai thư mục.report_partial_closure(): So sánh hai thư mục và thư mục con trực tiếp.report_full_closure(): So sánh đệ quy toàn bộ cây thư mục.
Và nhiều thuộc tính hữu ích: left_list, right_list, common, left_only, right_only, common_dirs, common_files, same_files, diff_files, funny_files, subdirs.
Chuẩn bị dữ liệu kiểm tra
import os
def makefile(filename, text=None):
with open(filename, 'w') as f:
f.write(text or filename)
def makedirectory(directory_name):
if not os.path.exists(directory_name):
os.mkdir(directory_name)
# Tạo cấu trúc thư mục test
present_directory = os.getcwd()
os.chdir('example') # Giả sử thư mục example đã tồn tại
os.mkdir('dir1')
os.mkdir('dir2')
os.mkdir('dir1/common_dir')
os.mkdir('dir2/common_dir')
os.mkdir('dir1/dir_only_in_dir1')
os.mkdir('dir2/dir_only_in_dir2')
makefile('dir1/file_only_in_dir1')
makefile('dir2/file_only_in_dir2')
makefile('dir1/common_file', 'Hello, Writing Same Content')
makefile('dir2/common_file', 'Hello, Writing Same Content')
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') # Tạo thư mục trùng tên file
os.chdir(present_directory)
Ví dụ so sánh file với cmp()
import filecmp
print('Common File:', filecmp.cmp('example/dir1/common_file', 'example/dir2/common_file'))
print('Common File (shallow=False):', filecmp.cmp('example/dir1/common_file', 'example/dir2/common_file', shallow=False))
print('Different Files:', filecmp.cmp('example/dir1/not_the_same', 'example/dir2/not_the_same'))
print('Different Files (shallow=False):', filecmp.cmp('example/dir1/not_the_same', 'example/dir2/not_the_same', shallow=False))
print('Identical Files:', filecmp.cmp('example/dir1/file_only_in_dir1', 'example/dir1/file_only_in_dir1'))
print('Identical Files (shallow=False):', filecmp.cmp('example/dir1/file_only_in_dir1', 'example/dir1/file_only_in_dir1', shallow=False))
Kết quả:
Common File: True True
Different Files: False False
Identical Files: True True
Ví dụ so sánh tập file với cmpfiles()
import filecmp
import os
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: {common_files}')
match, mismatch, errors = filecmp.cmpfiles('example/dir1', 'example/dir2', common_files)
print(f'Matched: {match}')
print(f'Mismatch: {mismatch}')
print(f'Errors: {errors}')
Kết quả:
Common files: ['file_in_dir1', 'not_the_same', 'common_file']
Matched: ['common_file']
Mismatch: ['file_in_dir1', 'not_the_same']
Errors: []
Ví dụ so sánh thư mục với dircmp()
import filecmp
dc = filecmp.dircmp('example/dir1', 'example/dir2')
print("Báo cáo chi tiết:")
print(dc.report())
print("\nBáo cáo đệ quy đầy đủ:")
print(dc.report_full_closure())
Kết quả: Hiển thị chi tiết file giống/khác, thư mục chỉ có ở một bên, các trường hợp đặc biệt (funny cases).