如何在python中递归复制目录并覆盖所有?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12683834/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to copy directory recursively in python and overwrite all?
提问by IAmYourFaja
I'm trying to copy /home/myUser/dir1/and all its contents (and their contents, etc.) to /home/myuser/dir2/in python. Furthermore, I want the copy to overwrite everything in dir2/.
我正在尝试将/home/myUser/dir1/其所有内容(及其内容等)复制到/home/myuser/dir2/python 中。此外,我希望副本覆盖dir2/.
It lookslike distutils.dir_util.copy_treemight be the right tool for the job, but not sure if there's anything easier/more obvious to use for such a simple task.
它看起来像distutils.dir_util.copy_tree可能是这个职位的合适的工具,但不能肯定是否有什么更容易/更明显,使用这样一个简单的任务。
If it is the right tool, how do I use it? According to the docsthere are 8 parameters that it takes. Do I have to pass all 8 are just src, dstand update, and if so, how (I'm brand new to Python).
如果它是正确的工具,我该如何使用它?根据文档,它需要 8 个参数。我是否必须通过所有 8 个都只是src,dst和update,如果是这样,如何(我是 Python 的新手)。
If there's something out there that's better, can someone give me an example and point me in the right direction? Thanks in advance!
如果有更好的东西,有人能给我一个例子并指出正确的方向吗?提前致谢!
采纳答案by Vicent
You can use distutils.dir_util.copy_tree. It works just fine and you don't have to pass every argument, only srcand dstare mandatory.
您可以使用distutils.dir_util.copy_tree. 它工作得很好,你不必传递每个参数,只有src并且dst是强制性的。
However in your case you can't use a similar tool likeshutil.copytreebecause it behaves differently: as the destination directory must not exist this function can't be used for overwriting its contents.
但是,在您的情况下,您不能使用类似的工具,shutil.copytree因为它的行为不同:因为目标目录必须不存在,因此该功能不能用于覆盖其内容。
If you want to use the cptool as suggested in the question comments beware that using the subprocessmodule is currently the recommended way for spawning new processes as you can see in the documentation of the os.system function.
如果您想cp按照问题注释中的建议使用该工具,请注意使用该subprocess模块是目前推荐的生成新进程的方法,如您在 os.system 函数的文档中所见。
回答by Michael
Have a look at the shutilpackage, especially rmtreeand copytree. You can check if a file / path exists with os.paths.exists(<path>).
看看shutil包,特别是rmtree和copytree。您可以检查文件/路径是否存在os.paths.exists(<path>)。
import shutil
import os
def copy_and_overwrite(from_path, to_path):
if os.path.exists(to_path):
shutil.rmtree(to_path)
shutil.copytree(from_path, to_path)
Vincent was right about copytreenot working, if dirs already exist. So distutilsis the nicer version. Below is a fixed version of shutil.copytree. It's basically copied 1-1, except the first os.makedirs()put behind an if-else-construct:
copytree如果目录已经存在,文森特关于不工作是正确的。distutils更好的版本也是如此。下面是一个固定版本的shutil.copytree. 它基本上是 1-1 复制的,除了第一个os.makedirs()放在 if-else-construct 后面:
import os
from shutil import *
def copytree(src, dst, symlinks=False, ignore=None):
names = os.listdir(src)
if ignore is not None:
ignored_names = ignore(src, names)
else:
ignored_names = set()
if not os.path.isdir(dst): # This one line does the trick
os.makedirs(dst)
errors = []
for name in names:
if name in ignored_names:
continue
srcname = os.path.join(src, name)
dstname = os.path.join(dst, name)
try:
if symlinks and os.path.islink(srcname):
linkto = os.readlink(srcname)
os.symlink(linkto, dstname)
elif os.path.isdir(srcname):
copytree(srcname, dstname, symlinks, ignore)
else:
# Will raise a SpecialFileError for unsupported file types
copy2(srcname, dstname)
# catch the Error from the recursive copytree so that we can
# continue with other files
except Error, err:
errors.extend(err.args[0])
except EnvironmentError, why:
errors.append((srcname, dstname, str(why)))
try:
copystat(src, dst)
except OSError, why:
if WindowsError is not None and isinstance(why, WindowsError):
# Copying file access times may fail on Windows
pass
else:
errors.extend((src, dst, str(why)))
if errors:
raise Error, errors
回答by mgrant
Here's a simple solution to recursively overwrite a destination with a source, creating any necessary directories as it goes. This does not handle symlinks, but it would be a simple extension (see answer by @Michael above).
这是一个简单的解决方案,可以使用源递归覆盖目标,并在执行过程中创建任何必要的目录。这不处理符号链接,但它是一个简单的扩展(参见上面@Michael 的回答)。
def recursive_overwrite(src, dest, ignore=None):
if os.path.isdir(src):
if not os.path.isdir(dest):
os.makedirs(dest)
files = os.listdir(src)
if ignore is not None:
ignored = ignore(src, files)
else:
ignored = set()
for f in files:
if f not in ignored:
recursive_overwrite(os.path.join(src, f),
os.path.join(dest, f),
ignore)
else:
shutil.copyfile(src, dest)

