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

Compare two versions of the same folder and get names of files that differs

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

main_folder
    |__ foo.json
    |
    |__ sub_folder
          |__bar.json

我有两份 main_folder,例如main_folder_v1main_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

问题是,如果它在 main_folder_v2 中更新,我会得到 ["foo.json"],但我永远不会得到 ["bar.json"],因为 [=20] 中的文件比较似乎=] 未执行

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

[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\Whosebug\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 函数修改为 return 文件列表,而不是按照评论之一的要求打印它们

@EDIT1:

  • 添加了生成器功能(作为个人练习),这是新的(也是首选的)样式,并且在目录很大的情况下不会消耗内存(!!需要Python3.3 或更高!!yield from 语句可以替换为下面的 2 行注释(foryield)它)