13. python difflib和filecmp文本比较模块
13.python difflib和filecmp文本比较模块
difflib 与 filecmp 的区别:
特点 | difflib |
filecmp |
---|---|---|
功能定位 | 详细比较文本内容,生成差异报告 | 快速判断文件或目录是否相同 |
输出结果 | 详细差异报告(支持 HTML 格式) | 布尔值或文件列表(相同、不同、错误) |
性能 | 逐行比较,性能较低 | 通过元数据快速比较,性能较高 |
适用场景 | 文本文件的详细差异分析 | 文件和目录的快速比较 |
使用复杂度 | 较高,需要处理文本内容 | 较低,直接比较文件或目录 |
difflib
实例1:两个字符串的差异对比
#!/usr/bin/python3
#_*_coding:utf-8_*_
import difflib
# 定义两段字符串
text1 = """Hello, world!
This is the first string.
Line 3 is unique to text1.
"""
text2 = """Hello, world!
This is the second string.
Line 3 is unique to text2.
"""
# 将字符串按行分割为列表
lines1 = text1.splitlines()
lines2 = text2.splitlines()
# 使用 difflib.unified_diff 生成差异报告
# diff = difflib.unified_diff(lines1, lines2, fromfile="text1", tofile="text2")
#使用compare() 输出差异对比
d = difflib.Differ()
diff = d.compare(lines1,lines2)
# 打印差异
print("\n".join(diff))
unified_diff输出:
compare输出:
符号及含义:
实例2:使用HTML格式美化对比
root@jiaxing:~/test-venv# cat test.py
#!/usr/bin/python3
#_*_coding:utf-8_*_
import difflib
# 定义两段字符串
text1 = """Hello, world!
This is the first string.
Line 3 is unique to text1.
"""
text2 = """Hello, world!
This is the second string.
Line 3 is unique to text2.
"""
# 将字符串按行分割为列表
lines1 = text1.splitlines()
lines2 = text2.splitlines()
d = difflib.HtmlDiff()
print(d.make_file(lines1,lines2))
root@jiaxing:~/test-venv#
root@jiaxing:~/test-venv# python3 test.py >/app/code/blog/index.html
html输出在浏览器中访问:
实例3:nginx文件对比
#!/usr/bin/python3
#_*_coding:utf-8_*_
import difflib
import sys
try:
textfile1 = sys.argv[1] #第一个文件路径参数
textfile2 = sys.argv[2] #第二个文件路径参数
except Exception as e:
print(f"Error:{str(e)}")
print("Usage: test.py filename1 filename2")
sys.exit()
def readfile(filename):
try:
with open(filename,'r') as f:
return f.readlines()
except Exception as e:
print(f"Read file Error:{str(e)}")
sys.exit() #退出脚本
def compare_file(textfile1,textfile2):
text1_line1 = readfile(textfile1) #readfile()函数获取分割后的字符串
text2_line2 = readfile(textfile2)
#实例化HtmlDiff
d = difflib.HtmlDiff()
result = d.make_file(text1_line1,text2_line2)
return result
if __name__ == '__main__':
result = compare_file(textfile1,textfile2)
with open('/app/code/blog/index.html','w') as f:
f.writelines(result)
输出:
filecmp
- 当我们进行代码审计和校验备份结果时,往往需要检查原始与目标目录的文件是否一致性,那么python的标准库已经自带了满足此需求的模块filecmp。
- filecmp可以实现文件、目录、遍历子目录的差异对比功能,即使文件同名也会对比其内容是否一致
常用方法说明
- filecmp提供了三个方法:cmp(单文件对比)、cmpfiles(多文件对比)、dircmp(目录对比)
单文件对比:filecmp.cmp(f1,f2,shallow=True)
- 如果f1和f2相同则返回True,不同返回False
- shallow默认为True,只比较文件的元数据(如文件大小、修改时间等),而不检查文件的实际内容
- shallow=False,则会进行“深度比较”,即不仅比较元数据,还会检查文件的实际内容
In [1]: import filecmp
In [2]: filecmp.cmp('./f1','./f2',shallow=True)
Out[2]: True
In [3]: filecmp.cmp('./f1','./f3',shallow=True)
Out[3]: False
In [4]: filecmp.cmp('./f1','./f3',shallow=False)
Out[4]: False
In [5]: filecmp.cmp('./f1','./f2',shallow=False)
Out[5]: True
多文件对比:filecmp.cmpfiles(f1,f2,shallow=True)
- 该方法返回三个列表:分别为匹配、不匹配、错误
- 匹配:两个目录下同时存在同名文件且内容也相同
- 不匹配:两个目录下同时存在同名文件但内容不相同
- 错误:两个目录下不同时存在的文件
示例:
#两个目录下md5值对比
(test-venv) root@jiaxing:~/test-venv# md5sum dir1/*
1181c1834012245d785120e3505ed169 dir1/f1
348bd3ce10ec00ecc29d31ec97cd5839 dir1/f2
40b134ab8a3dee5dd9760a7805fd495c dir1/f3
41d9737bc75ae8fa57b7a84a44fba01c dir1/f5
(test-venv) root@jiaxing:~/test-venv# md5sum dir2/*
1181c1834012245d785120e3505ed169 dir2/f1
348bd3ce10ec00ecc29d31ec97cd5839 dir2/f2
23ebe88c0224f4f4fc0b608216e98735 dir2/f3
45a62d3d5d3e946250904697486591bc dir2/f4
In [2]: filecmp.cmpfiles('dir1','dir2',['f1','f2','f3','f4','f5'])
Out[2]: (['f1', 'f2'], ['f3'], ['f4', 'f5'])
目录对比:filecmp.dircmp(a,b,[,ignore[,hide]])
- 该方法是 filecmp 模块中用于比较两个目录的内容和结构的函数。它提供了一个方便的方式来递归比较两个目录中的文件和子目录,并生成详细的比较结果。
filecmp.dircmp()参数解释:
a
:第一个目录的路径(字符串)。b
:第二个目录的路径(字符串)。ignore
:(可选)一个文件名列表,指定在比较时忽略的文件或目录名。hide
:(可选)一个文件名列表,指定在比较结果中隐藏的文件或目录名。
返回值:
filecmp.dircmp()
返回一个 dircmp
对象,该对象包含以下属性和方法:
left
:第一个目录的路径。right
:第二个目录的路径。left_list
:第一个目录中的文件和子目录列表。right_list
:第二个目录中的文件和子目录列表。common
:两个目录中都存在的文件和子目录。left_only
:仅存在于第一个目录中的文件和子目录。right_only
:仅存在于第二个目录中的文件和子目录。diff_files
:两个目录中内容不同的文件。same_files
:两个目录中内容相同的文件。report()
:打印比较结果的摘要。report_full_closure()
:递归打印所有子目录的比较结果。
实例1:比较两个目录内容
(test-venv) root@jiaxing:~/test-venv# cat test.py
#!/usr/bin/python3
#_*_coding:utf-8_*_
import filecmp
#比较两个目录
dircmp = filecmp.dircmp('dir1','dir2')
#打印计较结果
print("相同的文件:", dircmp.same_files)
print("不同的文件:", dircmp.diff_files)
print("仅存在于 dir1 的文件:", dircmp.left_only)
print("仅存在于 dir2 的文件:", dircmp.right_only)
#打印摘要报告
dircmp.report()
#递归打印所有子目录的比较结果
dircmp.report_full_closure()
(test-venv) root@jiaxing:~/test-venv#
(test-venv) root@jiaxing:~/test-venv# python3 test.py
相同的文件: ['f1', 'f2']
不同的文件: ['f3']
仅存在于 dir1 的文件: ['f5']
仅存在于 dir2 的文件: ['f4']
diff dir1 dir2
Only in dir1 : ['f5']
Only in dir2 : ['f4']
Identical files : ['f1', 'f2']
Differing files : ['f3']
diff dir1 dir2
Only in dir1 : ['f5']
Only in dir2 : ['f4']
Identical files : ['f1', 'f2']
Differing files : ['f3']
(test-venv) root@jiaxing:~/test-venv# tree dir1 dir2
dir1
├── f1
├── f2
├── f3
└── f5
dir2
├── f1
├── f2
├── f3
└── f4
实例2:比较两个目录内容
#!/usr/bin/python3
#_*_coding:utf-8_*_
import sys
import os
import filecmp
diff_files = [] #名称相同但不一致的文件(目录)列表
left_only = [] #第一个目录独有的文件(目录)列表
right_only = [] #第二个目录独有的文件(目录)列表
#从命令行获取要比较的目录路径
try:
dir1 = sys.argv[1]
dir2 = sys.argv[2]
except Exception as e:
print(f"Error: {e}")
print("使用方法:python3 test.py 目录1 目录2")
sys.exit()
"""处理目录的比较结果"""
def cmp_result(dcmp):
for item in dcmp.diff_files:
diff_files.append(os.path.join(dcmp.left,item))
for item in dcmp.left_only:
left_only.append(os.path.join(dcmp.left,item))
for item in dcmp.right_only:
right_only.append(os.path.join(dcmp.right,item))
for sub_dcmp in dcmp.subdirs.values(): #subdirs是一个字典
cmp_result(sub_dcmp) #递归处理子目录
if __name__ == "__main__":
dcmp = filecmp.dircmp(dir1,dir2)
cmp_result(dcmp)
diff_count = len(diff_files)
left_count = len(left_only)
right_count = len(right_only)
if (diff_count == 0 and left_count == 0 and right_count == 0):
print("两个目录完全一致")
else:
print("目录比较分析结果:")
print(dir1 + "目录中独有" + str(left_count) + "个文件:", left_only )
print(dir2 + "目录中独有" + str(right_count) + "个文件:", right_only)
print("名称相同但不一致的有" + str(diff_count) + "个文件", diff_files)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!