如何使用 Python 将整个文件目录复制到现有目录中?
从包含名为 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/
Do I need to use shutil.copy()
to copy every file in baz
into foo
? (在我已经使用 shutil.copytree()
将“bar”的内容复制到“foo”中之后?)还是有更简单/更好的方法?
Run the following code from a directory that contains a directory named bar
(containing one or more files) and a directory named baz
(also containing one or more files). Make sure there is not a directory named foo
.
import shutil
shutil.copytree('bar', 'foo')
shutil.copytree('baz', 'foo')
It will fail with:
$ 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'
I want this to work the same way as if I had typed:
$ mkdir foo
$ cp bar/* foo/
$ cp baz/* foo/
Do I need to use shutil.copy()
to copy each file in baz
into foo
? (After I've already copied the contents of 'bar' into 'foo' with shutil.copytree()
?) Or is there an easier/better way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
这是标准库的一部分的解决方案:
请参阅此类似问题。
使用 python 将目录内容复制到目录中
Here's a solution that's part of the standard library:
See this similar question.
Copy directory contents into a directory with python
标准
shutil.copytree
的这种限制看起来任意且令人讨厌。解决方法:请注意,它与标准
copytree
并不完全一致:根目录的
树;symlinks
和ignore
参数。代码>srcsrc
根级别的错误,它不会引发shutil.Error
;shutil.Error
,而不是尝试复制其他子树并引发单个组合的shutil.Error
。This limitation of the standard
shutil.copytree
seems arbitrary and annoying. Workaround:Note that it's not entirely consistent with the standard
copytree
:symlinks
andignore
parameters for the root directory of thesrc
tree;shutil.Error
for errors at the root level ofsrc
;shutil.Error
for that subtree instead of trying to copy other subtrees and raising single combinedshutil.Error
.Python 3.8 引入了
dirs_exist_ok
参数到 < a href="https://docs.python.org/3/library/shutil.html#shutil.copytree" rel="noreferrer">shutil.copytree
:因此,对于 Python 3.8+,这应该可以工作:
Python 3.8 introduced the
dirs_exist_ok
argument toshutil.copytree
:Therefore, with Python 3.8+ this should work:
对 atzz 对函数的回答略有改进,其中上述函数始终尝试将文件从源复制到目标。
在我上面的实现中,
我们应该复制。
我正在使用上面的函数和 scons 构建。它对我帮助很大,因为每次编译时我可能不需要复制整组文件..而只需要复制修改的文件。
In slight improvement on atzz's answer to the function where the above function always tries to copy the files from source to destination.
In my above implementation
we should copy.
I am using above function along with scons build. It helped me a lot as every time when I compile I may not need to copy entire set of files.. but only the files which are modified.
受 atzz 和 Mital Vora 启发的合并:
A merge one inspired by atzz and Mital Vora:
文档明确指出目标目录不应该不存在:
我认为你最好的选择是
os.walk
第二个和所有后续目录,copy2
目录和文件,并对目录执行额外的copystat
操作。毕竟,这正是copytree
所做的,如文档中所述。或者您可以复制
和copystat
每个目录/文件和os.listdir
而不是os.walk
。docs explicitly state that destination directory should not exist:
I think your best bet is to
os.walk
the second and all consequent directories,copy2
directory and files and do additionalcopystat
for directories. After all that's precisely whatcopytree
does as explained in the docs. Or you couldcopy
andcopystat
each directory/file andos.listdir
instead ofos.walk
.这受到 atzz 提供的原始最佳答案的启发,我只是添加了替换文件/文件夹逻辑。因此它实际上并不合并,而是删除现有文件/文件夹并复制新文件/文件夹:
取消注释 rmtree 以使其成为移动函数。
This is inspired from the original best answer provided by atzz, I just added replace file / folder logic. So it doesn't actually merge, but deletes the existing file/ folder and copies the new one:
Uncomment the rmtree to make it a move function.
这是我对这个问题的看法。我修改了copytree的源代码以保留原始功能,但现在当目录已经存在时不会发生错误。我还更改了它,这样它就不会覆盖现有文件,而是保留两个副本,其中一个副本的名称经过修改,因为这对我的应用程序很重要。
Here is my pass at the problem. I modified the source code for copytree to keep the original functionality, but now no error occurs when the directory already exists. I also changed it so it doesn't overwrite existing files but rather keeps both copies, one with a modified name, since this was important for my application.
这是一个需要
pathlib.Path
作为输入的版本。请注意,此函数需要 Python 3.6,这是
os.listdir()
支持类似路径对象作为输入的第一个 Python 版本。如果您需要支持早期版本的Python,可以将listdir(src)
替换为listdir(str(src))
。Here is a version that expects a
pathlib.Path
as input.Note that this function requires Python 3.6, which is the first version of Python where
os.listdir()
supports path-like objects as input. If you need to support earlier versions of Python, you can replacelistdir(src)
bylistdir(str(src))
.这是我对同一任务的版本::
Here is my version of the same task::
这是受此线程启发的版本,它更接近地模仿
distutils.file_util.copy_file
。updateonly
如果为 True,则为布尔值,将仅复制修改日期比dst
中现有文件更新的文件,除非在forceupdate
中列出,无论如何都会复制。ignore
和forceupdate
期望文件名或文件夹/文件名列表相对于src
并接受类似于 Unix 风格的通配符glob
或fnmatch
。该函数返回复制的文件列表(或者如果
dryrun
为True则将被复制)。Here is a version inspired by this thread that more closely mimics
distutils.file_util.copy_file
.updateonly
is a bool if True, will only copy files with modified dates newer than existing files indst
unless listed inforceupdate
which will copy regardless.ignore
andforceupdate
expect lists of filenames or folder/filenames relative tosrc
and accept Unix-style wildcards similar toglob
orfnmatch
.The function returns a list of files copied (or would be copied if
dryrun
if True).之前的解决方案存在一些问题,
src
可能会在没有任何通知或异常的情况下覆盖dst
。我添加了一个
predict_error
方法来在复制之前预测错误。copytree
主要基于 Cyrille Pontvieux 的版本。最好首先使用
predict_error
来预测所有错误,除非您希望在执行copytree
时看到另一个异常引发的异常,直到修复所有错误。The previous solution has some issue that
src
may overwritedst
without any notification or exception.I add a
predict_error
method to predict errors before copy.copytree
mainly base on Cyrille Pontvieux's version.Using
predict_error
to predict all errors at first is best, unless you like to see exception raised one by another when executecopytree
until fix all error.试试这个:
Try This:
我无法编辑上面的“Boris Dalstein”答案,因此这里是此代码的改进版本:
编辑所做的改进:
str
路径或pathlib.Path
对象。键入提示会有所帮助。I couldn't edit the "Boris Dalstein" answer above so here is the improved version of this code:
EDIT on the improvements made:
str
path orpathlib.Path
object. Type hint will help.您可以尝试这个简单的修复:
从 文档:
You can try this simple fix:
From the Documentation:
我假设最快和最简单的方法是让 python 调用系统命令...
例如..
Tar 和 gzip 目录...将目录解压并解压到所需位置。
啊?
i would assume fastest and simplest way would be have python call the system commands...
example..
Tar and gzip up the directory.... unzip and untar the directory in the desired place.
yah?