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

Python中如何递归复制目录且不覆盖目标目录?

解决shutil.copytree递归复制目录不覆盖目标内容的问题

shutil.copytree() 默认要求目标目录不存在,若强行用 dirs_exist_ok=True 参数允许目标存在,会覆盖同名文件。要实现合并式递归复制(不覆盖已有内容),可以用以下几种方案:

方法1:手动遍历目录,按需复制

遍历源目录的所有文件和子目录,仅当目标路径不存在时才执行复制,已存在的文件/目录直接跳过或递归合并。

import os
import shutil

def merge_copy(src_dir, dest_dir):
    # 确保目标父目录存在
    os.makedirs(dest_dir, exist_ok=True)
    
    for item_name in os.listdir(src_dir):
        src_item = os.path.join(src_dir, item_name)
        dest_item = os.path.join(dest_dir, item_name)
        
        if os.path.isdir(src_item):
            # 递归处理子目录
            merge_copy(src_item, dest_item)
        else:
            # 仅复制不存在的文件
            if not os.path.exists(dest_item):
                shutil.copy2(src_item, dest_item)
                print(f"已复制: {src_item} -> {dest_item}")
            else:
                print(f"跳过已存在文件: {dest_item}")

# 使用示例
merge_copy("source_dir_1", "target_dir")
merge_copy("source_dir_2", "target_dir")

方法2:自定义copytree的复制逻辑

利用 shutil.copytree() 的 copy_function 参数,自定义文件复制行为,跳过已存在的文件;配合 dirs_exist_ok=True 实现目录合并。

import os
import shutil

def safe_copy(src, dst):
    # 目标不存在时才复制,保留文件元数据
    if not os.path.exists(dst):
        shutil.copy2(src, dst)
    else:
        print(f"跳过已存在文件: {dst}")

def merge_copytree(src_dir, dest_dir):
    shutil.copytree(
        src_dir,
        dest_dir,
        copy_function=safe_copy,
        dirs_exist_ok=True
    )

# 使用示例
merge_copytree("source_dir_1", "target_dir")
merge_copytree("source_dir_2", "target_dir")

方法3:用pathlib简化路径操作(Python3.4+)

借助pathlib的面向对象API,更简洁地处理路径遍历和判断逻辑,核心逻辑和方法1一致。

from pathlib import Path
import shutil

def merge_copy_pathlib(src_dir, dest_dir):
    src_path = Path(src_dir)
    dest_path = Path(dest_dir)
    dest_path.mkdir(parents=True, exist_ok=True)
    
    for item in src_path.iterdir():
        dest_item = dest_path / item.name
        if item.is_dir():
            merge_copy_pathlib(item, dest_item)
        else:
            if not dest_item.exists():
                shutil.copy2(item, dest_item)
                print(f"已复制: {item} -> {dest_item}")
            else:
                print(f"跳过已存在文件: {dest_item}")

# 使用示例
merge_copy_pathlib("source_dir_1", "target_dir")
merge_copy_pathlib("source_dir_2", "target_dir")

内容的提问来源于stack exchange,提问作者tclemment

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 12:04:59