You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 05:45:48