Python之filecmp模块的使用
filecmp模块作用
主要用于比较文件系统上的文件和目录
1、创建演示的目录
import os def mkfile(filename, body=None): # 创建文件,内容没有设置则写入文件名,有传内容则传写指定的内容 with open(filename, 'w') as f: f.write(body or filename) return None def make_example_dir(top): if not os.path.exists(top): os.mkdir(top) # 获取当前的目录 curdir = os.getcwd() # 修改当前的目录位置 os.chdir(top) # 创建两个目录 os.mkdir('dir1') os.mkdir('dir2') # 创建两个文件 mkfile('dir1/file_only_in_dir1') mkfile('dir2/file_only_in_dir2') # 创建两个目录 os.mkdir('dir1/common_dir') os.mkdir('dir2/common_dir') # 创建一个文件并且写入指定的内容,并且创建一个软链接到dir2 mkfile('dir1/common_file', 'this file is the same') os.link('dir1/common_file', 'dir2/common_file') # 创建两个文件 mkfile('dir1/contents_differ') mkfile('dir2/contents_differ') # 更新访问时间和修改时间 st = os.stat('dir1/contents_differ') os.utime('dir2/contents_differ', (st.st_atime, st.st_mtime)) # 创建文件和目录 mkfile('dir1/file_in_dir1', 'This is a file in dir1') os.mkdir('dir2/file_in_dir1') # 恢复当前的目录 os.chdir(curdir) return None if __name__ == '__main__': os.chdir(os.path.dirname(__file__) or os.getcwd()) make_example_dir('example') make_example_dir('example/dir1/common_dir') make_example_dir('example/dir2/common_dir')
测试效果
2、比较文件内容
import filecmp # 比较common_file文件 # shallow=True : 只比较文件数据元信息。 print('common_file :', end=' ') print(filecmp.cmp('example/dir1/common_file', 'example/dir2/common_file', shallow=True), end=' ') # shallow=False : 除了比较文件数据元信息,还要读取文件内容比较。 print(filecmp.cmp('example/dir1/common_file', 'example/dir2/common_file', shallow=False)) # 比较contents_differ文件 print('contents_differ:', end=' ') print(filecmp.cmp('example/dir1/contents_differ', 'example/dir2/contents_differ', shallow=True), end=' ') print(filecmp.cmp('example/dir1/contents_differ', 'example/dir2/contents_differ', shallow=False)) # 比较file_only_in_dir*文件 print('contents_differ:', end=' ') print(filecmp.cmp('example/dir1/file_only_in_dir1', 'example/dir2/file_only_in_dir2', shallow=True), end=' ') print(filecmp.cmp('example/dir1/file_only_in_dir1', 'example/dir2/file_only_in_dir2', shallow=False))
测试效果
common_file : True True
contents_differ: True False
contents_differ: False False
3、批量比较文件的差异
import filecmp import os d1_contents = set(os.listdir('example/dir1')) d2_contents = set(os.listdir('example/dir2')) # 求交集,去重 common = list(d1_contents & d2_contents) # 判断是否是文件 common_files = [ f for f in common if os.path.isfile(os.path.join('example/dir1', f)) ] print('文件名', common_files) match, mismatch, errors = filecmp.cmpfiles( 'example/dir1', 'example/dir2', common_files ) print('匹配到 :', match) print('匹配不到 :', mismatch) print('错误 :', errors)
测试效果
文件名 ['common_file', 'contents_differ', 'file_in_dir1'] 匹配到 : ['common_file', 'contents_differ'] 匹配不到 : ['file_in_dir1'] 错误 : []
4、目录的比较差异
import filecmp dc = filecmp.dircmp('example/dir1', 'example/dir2') dc.report()
测试效果
diff example/dir1 example/dir2 Only in example/dir1 : ['file_only_in_dir1'] Only in example/dir2 : ['file_only_in_dir2'] Identical files : ['common_file', 'contents_differ'] Common subdirectories : ['common_dir'] Common funny cases : ['file_in_dir1']
5、所有同级目录的比较
import filecmp dc = filecmp.dircmp('example/dir1', 'example/dir2') dc.report_full_closure()
测试效果
diff example/dir1 example/dir2 Only in example/dir1 : ['file_only_in_dir1'] Only in example/dir2 : ['file_only_in_dir2'] Identical files : ['common_file', 'contents_differ'] 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', 'contents_differ', 'file_in_dir1', 'file_only_in_dir1'] Common subdirectories : ['common_dir'] diff example/dir1\common_dir\dir1\common_dir example/dir2\common_dir\dir1\common_dir diff example/dir1\common_dir\dir2 example/dir2\common_dir\dir2 Identical files : ['common_file', 'contents_differ', 'file_only_in_dir2'] Common subdirectories : ['common_dir', 'file_in_dir1'] diff example/dir1\common_dir\dir2\common_dir example/dir2\common_dir\dir2\common_dir diff example/dir1\common_dir\dir2\file_in_dir1 example/dir2\common_dir\dir2\file_in_dir1
6、指定参照目录,匹配左边或右边的差异
import filecmp import pprint dc = filecmp.dircmp('example/dir1', 'example/dir2') print('左边的差异') pprint.pprint(dc.left_list) print('右边的差异') pprint.pprint(dc.right_list)
测试效果
左边的差异 ['common_dir', 'common_file', 'contents_differ', 'file_in_dir1', 'file_only_in_dir1'] 右边的差异 ['common_dir', 'common_file', 'contents_differ', 'file_in_dir1', 'file_only_in_dir2']
7、指定忽略比较的文件名,进行文件比较
import filecmp import pprint dc = filecmp.dircmp('example/dir1', 'example/dir2', ignore=['common_file']) print('左边的差异') pprint.pprint(dc.left_list) print('右边的差异') pprint.pprint(dc.right_list)
测试效果
左边的差异 ['common_dir', 'contents_differ', 'file_in_dir1', 'file_only_in_dir1'] 右边的差异 ['common_dir', 'contents_differ', 'file_in_dir1', 'file_only_in_dir2']
8、比较每个目录唯一的差异和公共的目录显示
import filecmp import pprint dc = filecmp.dircmp('example/dir1', 'example/dir2') print('Common:') pprint.pprint(dc.common) print('左边的差异') pprint.pprint(dc.left_only) print('右边的差异') pprint.pprint(dc.right_list)
测试效果
Common: ['common_dir', 'common_file', 'contents_differ', 'file_in_dir1'] 左边的差异 ['file_only_in_dir1'] 右边的差异 ['common_dir', 'common_file', 'contents_differ', 'file_in_dir1', 'file_only_in_dir2'] Process finished with exit code 0
9、目录比较,分解显示文件名
import filecmp import pprint dc = filecmp.dircmp('example/dir1', 'example/dir2') print('Common:') pprint.pprint(dc.common) print('Directories') pprint.pprint(dc.common_dirs) print('Files:') pprint.pprint(dc.common_files) print('Funny:') pprint.pprint(dc.common_funny)
测试效果
Common: ['common_dir', 'common_file', 'contents_differ', 'file_in_dir1'] Directories ['common_dir'] Files: ['common_file', 'contents_differ'] Funny: ['file_in_dir1']
10、比较os.stat()文件信息,不比较文本内容
import filecmp import pprint dc = filecmp.dircmp('example/dir1', 'example/dir2') print('Same:') pprint.pprint(dc.same_files) print('Different') pprint.pprint(dc.diff_files) print('Funny:') pprint.pprint(dc.funny_files)
测试效果
Same: ['common_file', 'contents_differ'] Different [] Funny: [] Process finished with exit code 0
11、用字典类型,它将目录名映射到新的dircmp对象
import filecmp dc = filecmp.dircmp('example/dir1', 'example/dir2') print('Subdirectories:') print(dc.subdirs)
测试效果
Subdirectories: {'common_dir': <filecmp.dircmp object at 0x000001BB94AC39C8>}