比较同一文件夹的两个版本并获取不同文件的名称
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_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
问题是,如果它在 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 行注释(for
和 yield
)它)
假设我有以下简化的文件结构
main_folder
|__ foo.json
|
|__ sub_folder
|__bar.json
我有两份 main_folder
,例如main_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
问题是,如果它在 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 行注释(for
和yield
)它)