比较同一文件夹的两个版本,并获取不同文件的名称

时间:2018-05-03 14:45:33

标签: python python-3.x file-comparison

假设我有以下简化文件结构

Got 1.000000, 2.000000
Got 0.100000, 0.200000
Got 1.234000, 2.234000

我有main_folder |__ foo.json | |__ sub_folder |__bar.json 的两个副本,例如main_foldermain_folder_v1

我想比较两个版本并获取所有不同文件的名称(例如,如果main_folder_v2中的内容已更新,请获取"foo.json"

我使用下面的代码

main_folder_v2

问题是,如果import filecmp comparison_result = filecmp.dircmp(main_folder_v1, main_folder_v2) files_that_differs = comparison_result.diff_files 更新["foo.json"],我会得到main_folder_v2,但由于["bar.json"]中的文件比较似乎永远不会sub_folder没有执行

是否有可能使用filecmp递归比较文件夹并获取不同文件的名称或os.walk()是唯一的解决方案?

1 个答案:

答案 0 :(得分:3)

[Python]: filecmp - File and Directory Comparisons支持通过dircmp.subdirs进行递归遍历。无需os.walk(或任何其他类似功能)。

code.py

import sys
import filecmp
import os


main_folder_v1 = "dir_v1"
main_folder_v2 = "dir_v2"

ROOT_DIR_MARKER = ""


def traverse_dircmp(dircmp_obj, dir_name=ROOT_DIR_MARKER):
    for item in dircmp_obj.diff_files:
        yield os.path.join(dir_name, item)
    for subdir_name in dircmp_obj.subdirs:
        yield from traverse_dircmp(dircmp_obj.subdirs[subdir_name], dir_name=os.path.join(dir_name, subdir_name))
        #for item in traverse_dircmp(dircmp_obj.subdirs[subdir_name], dir_name=os.path.join(dir_name, subdir_name)):
        #    yield item


def traverse_dircmp_list(dircmp_obj, dir_name=ROOT_DIR_MARKER):
    ret = [os.path.join(dir_name, item) for item in dircmp_obj.diff_files]
    for subdir_name in dircmp_obj.subdirs:
        ret.extend(traverse_dircmp_list(dircmp_obj.subdirs[subdir_name], dir_name=os.path.join(dir_name, subdir_name)))
    return ret


def main():
    comparison_object = filecmp.dircmp(main_folder_v1, main_folder_v2)

    comparison_result = traverse_dircmp(comparison_object)
    print("{:s}: {:}".format("Different files (gen)", list(comparison_result)))

    comparison_result_list = traverse_dircmp_list(comparison_object)
    print("{:s}: {:}".format("Different files (list)", comparison_result_list))


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()

输出(对于与您类似的目录结构):

(py35x64_test) e:\Work\Dev\StackOverflow\q050157870>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" code.py
Python 3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32

Different files (gen): ['foo.json', 'subdir00\\bar.json', 'subdir00\\subdir001\\x.json']
Different files (list): ['foo.json', 'subdir00\\bar.json', 'subdir00\\subdir001\\x.json']

<强> @ EDIT0

  • 修改traverse_dircmp函数以返回文件列表,而不是按照其中一条评论的要求打印它们

<强> @ EDIT1

  • 添加了生成器功能(作为个人练习),这是新的(和首选)风格,并且在大型dirs的情况下不消耗内存( !!要求 Python3.3 或更高!! ,或yield from语句可以替换为其下方的2条注释(foryield)行。)