在一个目录中运行以下代码,该目录包含一个名为bar的目录(包含一个或多个文件)和一个名为baz的目录(也包含一个或多个文件)。确保没有名为foo的目录。

import shutil
shutil.copytree('bar', 'foo')
shutil.copytree('baz', 'foo')

它将失败:

$ python copytree_test.py 
Traceback (most recent call last):
  File "copytree_test.py", line 5, in <module>
    shutil.copytree('baz', 'foo')
  File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/shutil.py", line 110, in copytree
  File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/os.py", line 172, in makedirs
OSError: [Errno 17] File exists: 'foo'

我想让它像我输入的那样工作:

$ mkdir foo
$ cp bar/* foo/
$ cp baz/* foo/

我需要使用shutil.copy()复制每个文件在baz到foo?(在我已经用shutil.copytree()将'bar'的内容复制到'foo'后?)或者有更简单/更好的方法吗?


当前回答

Python 3.8向shutil.copytree引入了dirs_exist_ok参数:

递归地复制以src为根的整个目录树到名为dst的目录,并返回目标目录。Dirs_exist_ok指示在DST或任何缺失的父目录已经存在时是否引发异常。

因此,对于Python 3.8+,这应该可以工作:

import shutil

shutil.copytree('bar', 'foo')
shutil.copytree('baz', 'foo', dirs_exist_ok=True)

其他回答

Docs明确指出目标目录不应该存在:

以dst命名的目标目录必须不存在;它将被创建,同时还将创建缺失的父目录。

我觉得你最好的选择是。遍历第二个和所有后续目录、copy2目录和文件,并对目录执行额外的copyystat。毕竟,这正是copytree在文档中所做的解释。或者你可以复制和复制每个目录/文件和操作系统。而不是os.walk。

下面是一个需要pathlib的版本。路径作为输入。

# Recusively copies the content of the directory src to the directory dst.
# If dst doesn't exist, it is created, together with all missing parent directories.
# If a file from src already exists in dst, the file in dst is overwritten.
# Files already existing in dst which don't exist in src are preserved.
# Symlinks inside src are copied as symlinks, they are not resolved before copying.
#
def copy_dir(src, dst):
    dst.mkdir(parents=True, exist_ok=True)
    for item in os.listdir(src):
        s = src / item
        d = dst / item
        if s.is_dir():
            copy_dir(s, d)
        else:
            shutil.copy2(str(s), str(d))

注意,这个函数需要Python 3.6,这是Python的第一个版本,其中os.listdir()支持类似路径的对象作为输入。如果需要支持早期版本的Python,可以将listdir(str(src))替换为listdir(str(src))。

我认为最快最简单的方法是让python调用系统命令…

例子. .

import os
cmd = '<command line call>'
os.system(cmd)

Tar和gzip目录....将该目录解压缩并解压到所需的位置。

yah?

这是标准书板的局限性。Copytree似乎很随意,很烦人。处理:

import os, shutil
def copytree(src, dst, symlinks=False, ignore=None):
    for item in os.listdir(src):
        s = os.path.join(src, item)
        d = os.path.join(dst, item)
        if os.path.isdir(s):
            shutil.copytree(s, d, symlinks, ignore)
        else:
            shutil.copy2(s, d)

注意,它与标准复制树并不完全一致:

它不尊重符号链接,忽略SRC树根目录的参数; 它不提高shutil。src根级别的错误; 如果在复制子树期间发生错误,它将引发shutil。错误,而不是试图复制其他子树并引发单个组合shutil.Error。

Python 3.8向shutil.copytree引入了dirs_exist_ok参数:

递归地复制以src为根的整个目录树到名为dst的目录,并返回目标目录。Dirs_exist_ok指示在DST或任何缺失的父目录已经存在时是否引发异常。

因此,对于Python 3.8+,这应该可以工作:

import shutil

shutil.copytree('bar', 'foo')
shutil.copytree('baz', 'foo', dirs_exist_ok=True)