filecmp --- 文件及目录的比较│Python标准库

暗语寒飞 2021-02-22 11:15:12
Python 比较 目录 文件 filecmp


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

  • 系统类型: 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 语言及其相关知识。发掘更多原创文章,期待您的关注。
image

参考资料

官方文档

源代码

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

版权声明
本文为[暗语寒飞]所创,转载请带上原文链接,感谢
https://segmentfault.com/a/1190000039244022

  1. Detailed usage of urllib in Python 3 (header, proxy, timeout, authentication, exception handling)
  2. python 第三方库paramiko
  3. python 第三方库paramiko
  4. Python third party library paramiko
  5. Python third party library paramiko
  6. 卸载 PyCharm!这才是 Python 小白的最理想的 IDE
  7. 卸载 PyCharm!这才是 Python 小白的最理想的 IDE
  8. Uninstall pycharm! This is the ideal IDE for Python Xiaobai
  9. django学习-27.admin管理后台里:对列表展示页面的数据展示进行相关优化
  10. Uninstall pycharm! This is the ideal IDE for Python Xiaobai
  11. Django learning - 27. Admin management background: optimize the data display of the list display page
  12. python day2
  13. python day2
  14. Python 内存泄漏问题排查
  15. Troubleshooting of Python memory leak
  16. Python 与 excel的简单应用
  17. Simple application of Python and excel
  18. Python 与 excel的简单应用
  19. Simple application of Python and excel
  20. 2.7万 Star!最全面的 Python 设计模式集合
  21. 27000 stars! The most comprehensive collection of Python design patterns
  22. python day3
  23. python day3
  24. Commonly used data operation functions of Python
  25. (数据科学学习手札108)Python+Dash快速web应用开发——静态部件篇(上)
  26. (learning notes of data science 108) Python + dash rapid web application development -- static components (I)
  27. (数据科学学习手札108)Python+Dash快速web应用开发——静态部件篇(上)
  28. (learning notes of data science 108) Python + dash rapid web application development -- static components (I)
  29. [Python] Matplotlib 图表的绘制和美化技巧
  30. Drawing and beautifying skills of [Python] Matplotlib chart
  31. [Python] Matplotlib 图表的绘制和美化技巧
  32. Drawing and beautifying skills of [Python] Matplotlib chart
  33. Virtual environment of Python project
  34. 翻译:《实用的Python编程》02_01_Datatypes
  35. Translation: practical Python Programming 02_ 01_ Datatypes
  36. 翻译:《实用的Python编程》02_01_Datatypes
  37. 翻译:《实用的Python编程》02_01_Datatypes
  38. Translation: practical Python Programming 02_ 01_ Datatypes
  39. Translation: practical Python Programming 02_ 01_ Datatypes
  40. Python 3 入门,看这篇就够了
  41. Python 3 entry, see this is enough
  42. 华为大佬打造的400集Python视频学起来,学完万物皆可爬
  43. 400 episodes of Python video created by Huawei boss
  44. django之csrf_exempt解决跨域请求的问题
  45. CSRF of Django_ Exempt solves the problem of cross domain requests
  46. 1.7 万 Star!一个简单实用的 Python 进度条库
  47. 17000 stars! A simple and practical Python progress bar library
  48. Python爬虫:设置Cookie解决网站拦截并爬取蚂蚁短租
  49. Python crawler: setting cookie to solve website interception and crawling ant short rent
  50. Python-Net编程
  51. Python net programming
  52. 学习Python数学英语基础重要吗?Python教程!
  53. Is it important to learn the basics of math and English in Python!
  54. Python数据分析常用库有哪些?Python学习!
  55. What are the common libraries for Python data analysis? Learn Python!
  56. win 创建python虚拟环境
  57. Creating Python virtual environment with win
  58. In order to automatically collect B station barrage, I developed a tool in Python
  59. 用Python编程语言来实现阿姆斯特朗数的检查
  60. Using python programming language to check Armstrong number