• Python3标准库:filecmp比较文件


    1. filecmp比较文件

    filecmp模块提供了一些函数和一个类来比较文件系统上的文件和目录。

    1.1 示例数据

    使用下面代码创建一组测试文件。

    import os
    
    def mkfile(filename, body=None):
        with open(filename, 'w') as f:
            f.write(body or filename)
        return
    
    def make_example_dir(top):
        if not os.path.exists(top):
            os.mkdir(top)
        curdir = os.getcwd()
        os.chdir(top)
    
        os.mkdir('dir1')
        os.mkdir('dir2')
    
        mkfile('dir1/file_only_in_dir1')
        mkfile('dir2/file_only_in_dir2')
    
        os.mkdir('dir1/dir_only_in_dir1')
        os.mkdir('dir2/dir_only_in_dir2')
    
        os.mkdir('dir1/common_dir')
        os.mkdir('dir2/common_dir')
    
        mkfile('dir1/common_file', 'this file is the same')
        os.link('dir1/common_file', 'dir2/common_file')
    
        mkfile('dir1/contents_differ')
        mkfile('dir2/contents_differ')
        # Update the access and modification times so most of the stat
        # results will match.
        st = os.stat('dir1/contents_differ')
        os.utime('dir2/contents_differ', (st.st_atime, st.st_mtime))
    
        mkfile('dir1/file_in_dir1', 'This is a file in dir1')
        os.mkdir('dir2/file_in_dir1')
    
        os.chdir(curdir)
        return
    
    if __name__ == '__main__':
        os.chdir(os.path.dirname(__file__) or os.getcwd())
        make_example_dir('example')
        make_example_dir('example/dir1/common_dir')
        make_example_dir('example/dir2/common_dir')

    运行这个脚本会在axample目录下生成一个文件树。

    common_dir目录下也有同样的目录结构,以提供有意思的递归比较选择。 

    1.2 比较文件

    cmp()用于比较文件系统上的两个文件。

    import filecmp
    
    print('common_file    :', end=' ')
    print(filecmp.cmp('example/dir1/common_file',
                      'example/dir2/common_file',
                      shallow=True),
          end=' ')
    print(filecmp.cmp('example/dir1/common_file',
                      'example/dir2/common_file',
                      shallow=False))
    
    print('contents_differ:', end=' ')
    print(filecmp.cmp('example/dir1/contents_differ',
                      'example/dir2/contents_differ',
                      shallow=True),
          end=' ')
    print(filecmp.cmp('example/dir1/contents_differ',
                      'example/dir2/contents_differ',
                      shallow=False))
    
    print('identical      :', end=' ')
    print(filecmp.cmp('example/dir1/file_only_in_dir1',
                      'example/dir1/file_only_in_dir1',
                      shallow=True),
          end=' ')
    print(filecmp.cmp('example/dir1/file_only_in_dir1',
                      'example/dir1/file_only_in_dir1',
                      shallow=False))

    shallo参数告诉cmp()除了文件的元数据外,是否还要查看文件的内容。默认情况下,会使用由os.stat()得到的信息来完成一个浅比较。如果结果是一样的,则认为文件相同。因此,对于同时创建的相同大小的文件,即使他们的内容不同,也会报告为是相同的文件。当shallow为False时,则要比较文件的内容。

    如果非递归的比较两个目录中的一组文件,则可以使用cmpfiles()。参数是目录名和两个位置上要检查的我就爱你列表。传入的公共文件列表应当只包含文件名(目录会导致匹配不成功),而且这些文件在两个位置上都应当出现。下一个例子显示了构造公共列表的一种简单方法。与cmp()一样,这个比较也有一个shallow标志。 

    import filecmp
    import os
    
    # Determine the items that exist in both directories
    d1_contents = set(os.listdir('example/dir1'))
    d2_contents = set(os.listdir('example/dir2'))
    common = list(d1_contents & d2_contents)
    common_files = [
        f
        for f in common
        if os.path.isfile(os.path.join('example/dir1', f))
    ]
    print('Common files:', common_files)
    
    # Compare the directories
    match, mismatch, errors = filecmp.cmpfiles(
        'example/dir1',
        'example/dir2',
        common_files,
    )
    print('Match       :', match)
    print('Mismatch    :', mismatch)
    print('Errors      :', errors)

    cmpfiles()返回3个文件名列表,分别包含匹配的文件、不匹配的文件和不能比较的文件(由于权限问题或出于其他原因)。

    1.3 比较目录

    前面介绍的函数适合完成相对简单的比较。对于大目录树的递归比较或者更完整的分析,dircmp类很更有用。在最简单的用例中,report()会打印比较两个目录的报告。

    import filecmp
    
    dc = filecmp.dircmp('example/dir1', 'example/dir2')
    dc.report()

    输出是一个纯文本报告,显示的结果只包括给定目录的内容,而不会递归比较其子目录。在这里,认为文件not_the_same是相同的,因为这里没有比较内容。无法让dircmp像cmp()那样比较文件的内容。

    为了更多的细节,也为了完成一个递归比较,可以使用report_full_closure()。 

    import filecmp
    
    dc = filecmp.dircmp('example/dir1', 'example/dir2')
    dc.report_full_closure()

    输出将包括所有同级子目录的比较。 

    1.4 在程序中使用差异

    除了生成打印报告,dircmp还能计算文件列表,可以在程序中直接使用。以下各个属性只在请求时才计算,所以对于未用的数据,创建dircmp实例不会带来开销。

    import filecmp
    import pprint
    
    dc = filecmp.dircmp('example/dir1', 'example/dir2')
    print('Left:')
    pprint.pprint(dc.left_list)
    
    print('
    Right:')
    pprint.pprint(dc.right_list)

    所比较目录中包含的文件和子目录分别列在left_list和right_list中。

    可以向构造函数传入一个要忽略的名字列表(该列表中指定的名字将被忽略)来对输入进行过滤。默认的,RCS、CVS和tags等名字会被忽略。

    import filecmp
    import pprint
    
    dc = filecmp.dircmp('example/dir1', 'example/dir2',
                        ignore=['common_file'])
    
    print('Left:')
    pprint.pprint(dc.left_list)
    
    print('
    Right:')
    pprint.pprint(dc.right_list)

    在这里,将common_file从要比较的文件列表中去除。

    两个输入目录中共有的文件名会保存在common内,各目录独有的文件会列在left_only和right_only中。

    import filecmp
    import pprint
    
    dc = filecmp.dircmp('example/dir1', 'example/dir2')
    print('Common:')
    pprint.pprint(dc.common)
    
    print('
    Left:')
    pprint.pprint(dc.left_only)
    
    print('
    Right:')
    pprint.pprint(dc.right_only)

    "左"目录是dircmp()的第一个参数,"右"目录是第二个参数。

    公共成员可以被进一步分解为文件、目录和“有趣”元素(两个目录中类型不同的内容,或者os.stat()指出的有错误的地方)。

    import filecmp
    import pprint
    
    dc = filecmp.dircmp('example/dir1', 'example/dir2')
    print('Common:')
    pprint.pprint(dc.common)
    
    print('
    Directories:')
    pprint.pprint(dc.common_dirs)
    
    print('
    Files:')
    pprint.pprint(dc.common_files)
    
    print('
    Funny:')
    pprint.pprint(dc.common_funny)

    在示例数据中,file_in_dir1元素在一个目录中是一个文件,而在另一个目录中是一个子目录,所以它会出现在“有趣”列表中。

    文件之间的差别也可以做类似的划分。

    import filecmp
    
    dc = filecmp.dircmp('example/dir1', 'example/dir2')
    print('Same      :', dc.same_files)
    print('Different :', dc.diff_files)
    print('Funny     :', dc.funny_files)

    文件not_the_same通过os.stat()比较,并且不检查内容,所以它包含在same_files列表中。

    最后一点,子目录也会被保存,以便容易地完成递归比较。

    import filecmp
    
    dc = filecmp.dircmp('example/dir1', 'example/dir2')
    print('Subdirectories:')
    print(dc.subdirs)

    属性subdirs是一个字典,它将目录名映射到新的dircmp对象。

  • 相关阅读:
    Insus Meta Utility
    The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine.
    Insus Binary Utility
    asp.net实现文件下载功能
    Column 'Column Name' does not belong to table Table
    程序已被编译为DLL,怎样去修改程序功能
    如何在Web网站实现搜索功能
    如何把数据流转换为二进制字符串
    Asp.net更新文件夹的文件
    如何显示中文月份
  • 原文地址:https://www.cnblogs.com/liuhui0308/p/12489662.html
Copyright © 2020-2023  润新知