如何用Python将整个文件夹复制到已有目录中?

374 投票
15 回答
559183 浏览
提问于 2025-04-15 16:48

在一个包含名为 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' 之后)?还是有更简单或更好的方法呢?

15 个回答

159

Python 3.8 新增了一个叫做 dirs_exist_ok 的参数,这个参数是用在shutil.copytree 函数里的:

这个函数可以把一个目录及其所有内容从 src 复制到一个叫 dst 的目录,并返回目标目录。如果 dirs_exist_ok 设置了,就可以控制在目标目录 dst 或者它的上级目录已经存在的情况下,是否抛出错误。

所以,在 Python 3.8 及以上版本中,这样写应该是可以的:

import shutil

shutil.copytree('bar', 'foo')  # Will fail if `foo` exists
shutil.copytree('baz', 'foo', dirs_exist_ok=True)  # Fine
449

这里有一个解决方案,它是标准库的一部分:

from distutils.dir_util import copy_tree
copy_tree("/a/b/c", "/x/y/z")

你可以看看这个类似的问题。

用Python将目录内容复制到另一个目录

260

标准的 shutil.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)

需要注意的是,这个解决办法和标准的 copytree 方法并不完全一致:

  • 它对源目录的根目录不支持 symlinks(符号链接)和 ignore(忽略)参数;
  • 在源目录的根目录出现错误时,它不会抛出 shutil.Error 错误;
  • 如果在复制子目录时出现错误,它会只针对那个子目录抛出 shutil.Error,而不是尝试复制其他子目录并抛出一个合并的 shutil.Error

撰写回答