从我观察到的filecmp.dircmp是递归,但不满足我的需要,至少在py2.我想比较两个目录及其所有包含的文件.这是存在的,还是我需要构建(使用os.walk例如使用).我更喜欢预制,其他人已经完成了单元测试:)
实际的"比较"可以是草率的(例如,忽略权限),如果这有帮助的话.
我想要一些布尔值,并且report_full_closure是一份打印的报告.它也只是常见的子目录.AFIAC,如果左边或右边有任何东西,只有那些是不同的目标.我用它os.walk来构建它.
Mat*_*bos 24
这是比较功能与filecmp模块的替代实现.它使用递归代替os.walk,因此它更简单一些.但是,它并不仅仅通过使用common_dirs和subdirs属性来递归,因为在这种情况下我们将隐式使用文件比较的默认"浅层"实现,这可能不是你想要的.在下面的实现中,当比较具有相同名称的文件时,我们总是只比较它们的内容.
import filecmp
import os.path
def are_dir_trees_equal(dir1, dir2):
"""
Compare two directories recursively. Files in each directory are
assumed to be equal if their names and contents are equal.
@param dir1: First directory path
@param dir2: Second directory path
@return: True if the directory trees are the same and
there were no errors while accessing the directories or files,
False otherwise.
"""
dirs_cmp = filecmp.dircmp(dir1, dir2)
if len(dirs_cmp.left_only)>0 or len(dirs_cmp.right_only)>0 or \
len(dirs_cmp.funny_files)>0:
return False
(_, mismatch, errors) = filecmp.cmpfiles(
dir1, dir2, dirs_cmp.common_files, shallow=False)
if len(mismatch)>0 or len(errors)>0:
return False
for common_dir in dirs_cmp.common_dirs:
new_dir1 = os.path.join(dir1, common_dir)
new_dir2 = os.path.join(dir2, common_dir)
if not are_dir_trees_equal(new_dir1, new_dir2):
return False
return True
Run Code Online (Sandbox Code Playgroud)
Phi*_*nne 16
filecmp.dircmp是要走的路.但它没有比较两个比较目录中使用相同路径找到的文件的内容.而filecmp.dircmp只是查看文件属性.由于dircmp是一个类,您可以使用dircmp子类修复它,并覆盖其phase3比较文件的功能,以确保比较内容而不是仅比较os.stat属性.
import filecmp
class dircmp(filecmp.dircmp):
"""
Compare the content of dir1 and dir2. In contrast with filecmp.dircmp, this
subclass compares the content of files with the same path.
"""
def phase3(self):
"""
Find out differences between common files.
Ensure we are using content comparison with shallow=False.
"""
fcomp = filecmp.cmpfiles(self.left, self.right, self.common_files,
shallow=False)
self.same_files, self.diff_files, self.funny_files = fcomp
Run Code Online (Sandbox Code Playgroud)
然后你可以用它来返回一个布尔值:
import os.path
def is_same(dir1, dir2):
"""
Compare two directory trees content.
Return False if they differ, True is they are the same.
"""
compared = dircmp(dir1, dir2)
if (compared.left_only or compared.right_only or compared.diff_files
or compared.funny_files):
return False
for subdir in compared.common_dirs:
if not is_same(os.path.join(dir1, subdir), os.path.join(dir2, subdir)):
return False
return True
Run Code Online (Sandbox Code Playgroud)
如果您想重复使用此代码段,则特此专用于您选择的Public Domain或Creative Commons CC0(除了SO提供的默认许可证CC-BY-SA).
这是一个带有递归函数的简单解决方案:
import filecmp
def same_folders(dcmp):
if dcmp.diff_files or dcmp.left_only or dcmp.right_only:
return False
for sub_dcmp in dcmp.subdirs.values():
if not same_folders(sub_dcmp):
return False
return True
same_folders(filecmp.dircmp('/tmp/archive1', '/tmp/archive2'))
Run Code Online (Sandbox Code Playgroud)
该report_full_closure()方法是递归的:
comparison = filecmp.dircmp('/directory1', '/directory2')
comparison.report_full_closure()
Run Code Online (Sandbox Code Playgroud)
编辑:OP编辑后,我会说最好只使用其他功能filecmp.我觉得没os.walk必要; 最好简单地通过由common_dirs等产生的列表进行递归,尽管在某些情况下(大型目录树),如果实施不当,这可能会导致Max Recursion Depth错误.
dircmp可以是递归的:参见report_full_closure.
据我所知dircmp不提供目录比较功能。不过,自己编写也很容易;使用left_onlyand right_onlyondircmp检查目录中的文件是否相同,然后对subdirs属性进行递归。