zoukankan      html  css  js  c++  java
  • 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 = "
    ".join(diff_result)
    print("字符对比结果>>>:
    {}".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()
    
  • 相关阅读:
    【Java基础】多态
    inner join / left join / right join
    Java并发之AQS详解
    AQS实现公平锁和非公平锁
    进程与线程区别是什么
    【java设计模式】代理模式
    Spring中用到的设计模式
    【Java设计模式】工厂模式
    前端开发 —— 本地化
    前端开发 —— Blade 模板引擎
  • 原文地址:https://www.cnblogs.com/zhaokunhao/p/15003998.html
Copyright © 2011-2022 走看看