使用filecmp.cmp比对文件与列表实现过滤复制的开发问题
Python文件内容比对排除复制方案
原有代码问题说明
你当前写的嵌套循环逻辑存在错误:只要待复制文件和某一个排除列表内的文件内容不一致,就会触发一次复制操作,会出现重复复制、匹配到同内容文件时仍误复制的问题。
filecmp.cmp()用法说明
filecmp.cmp(file1, file2, shallow=True) 用于比对两个文件是否相同,参数规则如下:
file1、file2:待比对的两个文件的完整路径字符串shallow:可选参数,默认值为True- 为
True时仅比对文件的元数据(文件大小、最后修改时间等),比对速度快,适合大批量小文件场景 - 为
False时会逐字节读取两个文件的内容做完整比对,准确率更高,大文件场景下耗时更长,你可以根据业务需求选择
- 为
修正后的基础实现代码
import filecmp import shutil def copy_files(self, list_to_copy, list_to_avoid, destination): for copied_file in list_to_copy: # 标记是否允许复制,默认允许 allow_copy = True # 和排除列表所有文件逐一比对 for avoid_file in list_to_avoid: if filecmp.cmp(copied_file, avoid_file, shallow=False): # 匹配到同内容文件,禁止复制并跳出比对循环 allow_copy = False break # 仅无匹配的同内容排除文件时执行复制 if allow_copy: shutil.copy(copied_file, destination)
大文件/多排除文件场景优化方案
如果排除列表文件数量多、文件体积大,两两逐一遍历比对的性能较低,可以预先计算所有排除文件的哈希值,再和待复制文件的哈希值做比对,减少重复IO操作:
import hashlib import shutil def get_file_hash(file_path, block_size=65536): """计算文件MD5哈希值,block_size可根据硬件配置调整""" hasher = hashlib.md5() with open(file_path, 'rb') as f: for block in iter(lambda: f.read(block_size), b''): hasher.update(block) return hasher.hexdigest() def copy_files(self, list_to_copy, list_to_avoid, destination): # 预计算所有排除文件的哈希值集合 avoid_hash_set = set(get_file_hash(f) for f in list_to_avoid) for copied_file in list_to_copy: current_hash = get_file_hash(copied_file) if current_hash not in avoid_hash_set: shutil.copy(copied_file, destination)
内容的提问来源于stack exchange,提问作者VERX
相关产品推荐
相关产品推荐

