Python:shutil.copytree替代方案及多目录复制冲突解决
解决shutil.copytree多目录复制冲突问题
核心问题分析
你遇到的问题根源是直接将shutil.copytree的dst参数设为已存在的目标目录:要么触发"文件已存在"错误,要么设置dirs_exist_ok=True后直接覆盖目标目录内原有内容。正确思路是将源目录作为子目录复制到目标目录下,而非直接覆盖目标目录本身。
以下是几种可行解决方案:
方案1:指定正确的目标子路径(最简方案)
调用copytree时,将目标路径拼接为「父目标目录 + 源目录名称」,每次复制都会在目标目录下生成对应源目录的子文件夹,避免覆盖或报错:
import os import shutil def copy_to_target_dir(src, target_parent): # 拼接目标路径:父目录下创建与源目录同名的子目录 target_path = os.path.join(target_parent, os.path.basename(src)) # dirs_exist_ok=True允许子目录已存在时,合并源目录的新内容(已存在文件会覆盖) shutil.copytree(src, target_path, dirs_exist_ok=True) # 示例调用 copy_to_target_dir("/home/user/source_dir1", "/home/user/target_root") copy_to_target_dir("/home/user/source_dir2", "/home/user/target_root")
方案2:自定义复制函数,避免覆盖已存在文件
如果需要保留目标目录中已存在的文件,可自定义copy_function参数,在复制前检查文件是否存在,存在则跳过:
import os import shutil def safe_copy(src_file, dst_file, follow_symlinks=True): if os.path.exists(dst_file): print(f"已存在文件,跳过:{dst_file}") return # 使用copy2保留文件元数据(比copy更完整) shutil.copy2(src_file, dst_file, follow_symlinks=follow_symlinks) def safe_copy_dir(src, target_parent): target_path = os.path.join(target_parent, os.path.basename(src)) shutil.copytree(src, target_path, dirs_exist_ok=True, copy_function=safe_copy) # 示例调用 safe_copy_dir("/home/user/source_dir1", "/home/user/target_root") safe_copy_dir("/home/user/source_dir2", "/home/user/target_root")
方案3:手动遍历目录实现精细控制
如果需要更灵活的逻辑(比如跳过特定类型文件、记录复制日志等),可以手动遍历源目录结构,逐个复制文件和子目录:
import os import shutil def manual_copy_directory(src, target_parent): target_dir = os.path.join(target_parent, os.path.basename(src)) # 确保目标子目录存在,不存在则创建 os.makedirs(target_dir, exist_ok=True) for item_name in os.listdir(src): src_item = os.path.join(src, item_name) dst_item = os.path.join(target_dir, item_name) if os.path.isdir(src_item): # 递归处理子目录 manual_copy_directory(src_item, target_dir) else: # 仅复制不存在的文件 if not os.path.exists(dst_item): shutil.copy2(src_item, dst_item) else: print(f"跳过已存在文件:{dst_item}") # 示例调用 manual_copy_directory("/home/user/source_dir1", "/home/user/target_root") manual_copy_directory("/home/user/source_dir2", "/home/user/target_root")
内容的提问来源于stack exchange,提问作者PatrickRKa
相关产品推荐
相关产品推荐

