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()
posted @ 2021-07-12 21:16  BaiM0  阅读(52)  评论(0编辑  收藏  举报