关于python:filecmp-文件及目录的比较│Python标准库

7次阅读

共计 4051 个字符,预计需要花费 11 分钟才能阅读完成。

前情提醒: 测试代码中,右尖括号(>)表示命令行中输出的命令;独自一行并以井字符(#)结尾的为输入内容;库的导入仅在本文的第一个测试代码中展示,其余代码块均省略库的导入代码。

  • 零碎类型: Windows 10
  • python 版本: Python 3.9.0

filecmp 模块能够用于文件与文件之间或目录与目录之间的比拟。并且能够通过设置参数来选取多种不同用时和不同准确性的计划。

filecmp 模块在进行文件或目录比照时,最终仅能返回是否相等这一后果。某些场景须要更加具体的后果阐明,能够应用 difflib 规范库。

快捷函数

filecmp.cmp(f1, f2, shallow=True)
参数:
    f1, f2: 要进行比拟的两个文件
    shallow: 关键字参数, 参数值为布尔值, 默认为 True;
             如果为 True, 则判断两文件须要具备雷同的 os.stat() 签名才会认为是相等的;
             如果为 False, 则比拟两文件的内容;
返回值:
    布尔值, 两个文件是否相等

比拟 f1f2 的文件,如果它们仿佛相等则返回 True,否则返回 False。在官网文档中用上了 ‘ 仿佛 ’ 一词,这让人感觉有什么隐秘的信息文档上没有表达出来。

import filecmp
import os

'''本次测试代码中存在 4 个待比照文件, 其中 文件 1 与 文件 2 内容不同, 文件 3 与 文件 4 内容雷同'''
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

当比拟内容雷同的 文件 1 文件 2 时,参数 shallow 无论设置为 True 还是 False 后果都是 True。依照文档所述,文件 1 文件 2 os.stat() 是不雷同的,当参数 shallow 设置为 True 时,依据两个文件的 os.stat() 最终应该失去 False。为什么理论运行和文档形容不同呢?

查阅一些材料后,找到了一个比拟正当的解释,当参数 shallow 设置为 True,那么 os.stat() 雷同的会间接被视为相等,当两个文件的 os.stat() 不同时,依旧会比照文件中的内容。

另外,此函数会缓存比拟后果,在下次比拟时间接返回缓存后果。如果文件的 os.stat() 变动了,也就是文件被批改了,缓存主动生效。缓存也能用下文中的 filecmp.clear_cache() 函数革除。

filecmp.cmpfiles(dir1, dir2, common, shallow=True)
参数:
    dir1, dir2: 目录
    common: 须要比照的文件名列表
    shallow: 关键字参数, 参数值为布尔值, 默认为 True;
             如果为 True, 则判断两文件须要具备雷同的 os.stat() 签名才会认为是相等的;
             如果为 False, 则比拟两文件的内容;
返回值:
    元组, 蕴含三个类型为列表的元素.

比拟两个目录下的指定文件,返回比照后果,返回值是蕴含三个类型为列表的元素的元组。

'''
文件目录如下, 其中, 两个目录内的 文件 a 内容雷同, 文件 c 内容不同
- 目录 1
    - 文件 a
    - 目录 b
        - 文件 c
    - 文件 d
- 目录 2
    - 文件 a
    - 目录 b
        - 文件 c
'''''' 比照两目录下的文件 '''print(filecmp.cmpfiles(' 目录 1',' 目录 2', [' 文件 a',' 目录 b / 文件 c',' 文件 d']))
# (['文件 a'], ['目录 b / 文件 c'], ['文件 d'])

参数 common 列举要比照的文件名,别离比照两个目录下的同名文件,如果两个文件雷同,则退出返回值的第一个元素内; 如果两个文件内容不同,则退出返回值的第二个元素内; 如果文件无权限读取或者文件在任一目录内缺失,则退出返回值的第三个元素内;

参数 shallow 与上文中 filecmp.cmp() 函数意义雷同。

filecmp.clear_cache()

革除 filecmp 缓存。个别状况下,文件批改后,文件的 os.stat() 天然会扭转,缓存也会主动生效。然而如果文件被过快的批改,以至于超过底层文件系统记录批改工夫的精度时,那么尔后的文件比照将可能会呈现问题,此函数就是为了解决这个问题。

然而,这种文件过快的批改不晓得怎么测试进去? 大家有晓得的吗?

dircmp 类

class filecmp.dircmp(a, b, ignore=None, hide=None)
参数:
    a, b: 目录
    ignore: 关键字参数, 须要疏忽的文件名列表, 默认为 filecmp.DEFAULT_IGNORES
    hide: 关键字参数, 须要暗藏的文件名列表, 默认为 [os.curdir, os.pardir]

创立一个用于比拟两个目录的目录比拟对象。参数 ignore 可疏忽指定的文件名,hide 可暗藏指定的文件名。

print(filecmp.DEFAULT_IGNORES)
# ['RCS', 'CVS', 'tags', '.git', '.hg', '.bzr', '_darcs', '__pycache__']
print(os.curdir)
# .
print(os.pardir)
# ..

dircmp 类中有许多属性,这里应用测试代码间接展现:

dircmp_test = filecmp.dircmp('目录 1', '目录 2')

'''第一个 (绝对右边) 参数, 也是第一个目录的名称'''
print(dircmp_test.left)
# 目录 1

'''第二个 (绝对左边) 参数, 也是第二个目录的名称'''
print(dircmp_test.right)
# 目录 2

'''经参数 hide 与参数 ignore 过滤后, 第一个目录内的所有文件与子目录'''
print(dircmp_test.left_list)
# ['文件 a', '文件 d', '目录 b']

'''经参数 hide 与参数 ignore 过滤后, 第二个目录内的所有文件与子目录'''
print(dircmp_test.right_list)
# ['文件 a', '目录 b']

'''同时存在两个目录下的文件与子目录'''
print(dircmp_test.common)
# ['文件 a', '目录 b']

'''仅存在第一个目录下的文件与子目录'''
print(dircmp_test.left_only)
# ['文件 d']

'''仅存在第二个目录下的文件与子目录'''
print(dircmp_test.right_only)
# []

'''同时存在两个目录下的子目录'''
print(dircmp_test.common_dirs)
# ['目录 b']

'''将 common_dirs 属性值映射为 dircmp 对象的字典'''
print(dircmp_test.subdirs)
# {'目录 b': <filecmp.dircmp object at 0x000002A9A1374F70>}

'''同时存在两个目录下的文件'''
print(dircmp_test.common_files)
# ['文件 a']

'''在两个目录中类型不同的名字,或者那些 os.stat() 报告谬误的名字'''
print(dircmp_test.common_funny)
# []

'''在两个目录下, 应用类的比拟操作符雷同的文件'''
print(dircmp_test.same_files)
# ['文件 a']

'''在两个目录下, 应用类的比拟操作符不同的文件'''
print(dircmp_test.diff_files)
# []

'''无奈比拟的文件'''
print(dircmp_test.funny_files)
# []

dircmp 类也提供了一些用于打印信息的办法,同样,间接在测试用例中展现:

'''将 a 与 b 之间的比拟打印'''
dircmp_test.report()
# diff 目录 1 目录 2
# Only in 目录 1 : ['文件 d']
# Identical files : ['文件 a']
# Common subdirectories : ['目录 b']

'''打印 a 与 b 及独特间接子目录的比拟后果'''
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 及独特子目录比拟后果(递归地)'''
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']

公众号 :「python 杂货铺」,专一于 python 语言及其相干常识。挖掘更多原创文章,期待您的关注。

参考资料

官网文档

源代码

python – filecmp.cmp()疏忽不同的 os.stat()签名?

正文完
 0