04 difflib和filecmp
文件内容的差异对比
配置级别的变动,difflib自带,无需安装
字符对比
# 系统命令
[root@docker test]# echo nihao > nihao.txt
[root@docker test]# echo nihao1 > nihao1.txt
[root@docker test]# diff nihao.txt nihao1.txt
1c1
< nihao
---
> nihao1
# 模块介绍
difflib -- 实现字符串的差异对比,然后以版本控制风格进行输出
1、传递文件内容,然后进行简单的切割
2、创建Differ对象
3、在Differ对象的基础上,借助于compare方法将两个内容进行比较
4、结果以join的方式展示
# 应用
import difflib
# 准备第一个文件
text1 = '''nihao
woshi
baim0
'''
text1_line = text1.splitlines()
# 准备第二个文件
text2 = '''nihao
woshi
Baim0
'''
text2_line = text2.splitlines()
# 进行比较
# 创建文件对象
differ_object = difflib.Differ()
# 使用compare方法比较内容
diff_result = differ_object.compare(text1_line, text2_line)
# 拼接比较后的效果
result_message = "\n".join(diff_result)
print("字符对比结果>>>:\n{}".format(result_message))
格式输出
# 简介
HtmlDiff()类的make_file()方法,生成美观的html文档
# 操作步骤
1、传递文件内容,然后进行简单的行切割
2、创建HtmlDiff对象
3、在HtmlDiff对象的基础上,借助make_file方法将两个内容进行比骄傲
4、直接查看生成的对比文件
# 对比效果
1、颜色
2、统计
# 实践
import difflib
# 准备第一个文件
text1 = '''
nihao
woshi
baim0
'''
text1_line = text1.splitlines()
# 准备第二个文件
text2 = '''
nihao
woshi
Baim0
'''
text2_line = text2.splitlines()
# 进行比较
# 创建文件对象
Html_object = difflib.HtmlDiff()
# 使用compare方法比较内容
Html_result = Html_object.make_file(text1_line, text2_line)
# 查看
# print(Html_result)
# 输出到文件中
with open('/root/diff.html', 'w', encoding='utf-8') as f:
f.write(Html_result)
实践
# 实践需求
读取多个配置文件通过htmldiff比较文件的区别
#!/usr/bin/python3.6.7
import difflib
import sys
# /etc/nginx/nginx.conf
# /etc/nginx/nginx.conf.default
try:
textfile1 = sys.argv[1]
textfile2 = sys.argv[2]
except Exception as e:
print("文件路径错误!")
print("使用方式:scriptname filename1 filename2")
sys.exit()
def readfile(filename):
try:
with open(filename, 'r', encoding='utf-8') as f:
text = f.read().splitlines()
return text
except Exception as error:
print("文件内容读取失败!")
sys.exit()
if textfile1 == '' or textfile2 == '':
print("脚本的参数不允许为空,请检查")
print("使用方式:scriptname filename1 filename2")
text1_lines = readfile(textfile1)
text2_lines = readfile(textfile2)
Html_object = difflib.HtmlDiff()
Html_result = Html_object.make_file(text1_lines, text2_lines)
with open('/root/nginx_diff.html', 'w', encoding='utf-8') as f:
f.write(Html_result)
文件目录的差异对比
文件级别的变动
模块简介
cmp 单文件对比
cmpfiles 多文件对比
dircmp 目录文件对比
单文件对比
>>> import filecmp
>>>
>>>
>>> filecmp.cmp('/etc/nginx/nginx.conf','/etc/nginx/nginx.conf')
True
>>> filecmp.cmp('/etc/nginx/nginx.conf','/etc/nginx/nginx.conf.default')
False
多文件对比
>>> import filecmp
>>>
>>>
>>> filecmp.cmpfiles('/etc/nginx/','/etc/nginx/',["nginx.conf","uwsgi_params"])
>>> filecmp.cmpfiles('/etc/nginx/','/etc/nginx/',["nginx.conf","uwsgi_params"])
(['nginx.conf', 'uwsgi_params'], [], [])
# 第一个列表是相同的文件,第二个是不同的,第三个是不存在无法比较的
目录对比
>>> import filecmp
>>>
>>>
>>> object=filecmp.dircmp('/etc/nginx/','/etc/nginx/',igon=NONE默认)
>>> object.report()
diff /etc/nginx/ /etc/nginx/
Identical files : ['fastcgi.conf', 'fastcgi.conf.default', 'fastcgi_params', 'fastcgi_params.default', 'koi-utf', 'koi-win', 'mime.types', 'mime.types.default', 'nginx.conf', 'nginx.conf.default', 'scgi_params', 'scgi_params.default', 'uwsgi_params', 'uwsgi_params.default', 'win-utf']
Common subdirectories : ['conf.d', 'default.d']
综合实践
#!/usr/bin/python3.6.7
import os, sys
import filecmp
import re # 正则模块
import shutil # 文件的拷贝
holderlist = []
def compareme(dir1, dir2):
"""
对文件目录进行比对,获取所有的文件信息
:param dir1: 源代码目录结构
:param dir2: 目标目录结构
:return:holderlist 返回统计后的文件列表(列表推导式获取)
"""
# 1、对两个目录进行比较
dircomp = filecmp.dircmp(dir1, dir2)
# 2、获取需要同步的信息
only_in_one = dircomp.left_only # 左侧仅有的文件
diff_in_one = dircomp.diff_files # 不匹配的文件信息
# 3、更新临时存储的文件列表
dirpath = os.path.abspath(dir1)
# 获取左侧唯一的内容
[holderlist.append(
os.path.abspath(os.path.join(dir1, x))
) for x in only_in_one]
# 获取不一样的内容
[holderlist.append(
os.path.abspath(os.path.join(dir1, x))
) for x in diff_in_one]
# 4、递归方式获取所有文件信息
if len(dircomp.common_dirs) > 0:
for item in dircomp.common_dirs:
compareme(os.path.abspath(os.path.join(dir1, item)),
os.path.abspath(os.path.join(dir2, item)))
# 5、返回更新后的文件列表
return holderlist
def main():
# 接收两个目录路径
if len(sys.argv) > 2:
dir1 = sys.argv[1]
dir2 = sys.argv[2]
else:
print("脚本使用方式:脚本名 目录1 目录2")
sys.exit()
source_files = compareme(dir1, dir2) # 待同步的目录
dir1 = os.path.abspath(dir1) # dir1的绝对路径
destination_files = [] # 要同步的目录路径
createdir_bool = False # 是否要创建目录
# 目录创建
# 获取待同步的所有目录结构
for item in source_files:
destination_dir = re.sub(dir1, dir2, item)
destination_files.append(destination_dir)
if not os.path.exists(destination_dir):
os.makedirs(destination_dir)
createdir_bool = True
# 更新同步目录
if createdir_bool:
destination_files = []
source_files = compareme(dir1, dir2)
for item in source_files:
destination_dir = re.sub(dir1, dir2, item)
destination_files.append(destination_dir)
# 文件同步
print("update item:")
# 输出更新项列表清单
print(source_files)
# 将源目录与备份目录文件清单拆分成元祖
copy_pair = zip(source_files, destination_files)
for item in copy_pair:
# 判断是否为文件,是则进行复制操作
if os.path.isfile(item[0]):
shutil.copyfile(item[0], item[1])
if __name__ == '__main__':
main()