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

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

  • 零碎类型: 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文件2os.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()签名?

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理