我正在尝试将/home/myUser/dir1/
及其所有内容(及其内容等)复制到python中的/home/myuser/dir2/
。此外,我希望副本覆盖dir2/
中的所有内容。
看起来就像distutils.dir_util.copy_tree
可能是工作的正确工具,但不确定是否有更容易/更明显的用于这样一个简单的任务。
如果它是正确的工具,我该如何使用它?根据{{3}},它有8个参数。我必须通过所有8个只是src
,dst
和update
,如果是,我是如何(我是Python的新手)。
如果有更好的东西,有人可以给我一个例子并指出我正确的方向吗?提前谢谢!
答案 0 :(得分:52)
您可以使用distutils.dir_util.copy_tree
。它工作正常,您不必传递每个参数,只有src
和dst
是强制性的。
但是在您的情况下,您不能使用类似shutil.copytree
之类的工具,因为它的行为不同:因为目标目录不能存在,所以此功能不能用于覆盖其内容。
如果您想使用问题评论中建议的cp
工具,请注意使用subprocess
模块目前是产生新流程的推荐方法,如{{3}中所示}。
答案 1 :(得分:30)
查看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)
如果dirs已经存在,Vincent对于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
答案 2 :(得分:20)
这是一个简单的解决方案,用源递归覆盖目标,随时创建任何必要的目录。这不会处理符号链接,但它只是一个简单的扩展(请参阅@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)
答案 3 :(得分:7)
在Python 3.8中,dirs_exist_ok
关键字参数was added到shutil.copytree()
:
dirs_exist_ok
决定是否在dst
或任何丢失的父目录已经存在的情况下引发异常。
因此,即使目标目录已存在,以下内容也可以在最新版本的Python中运行:
shutil.copytree(src, dest, dirs_exist_ok=True) # 3.8+ only!
一个主要好处是它比distutils.dir_util.copy_tree()
更具灵活性,因为它需要忽略文件上的其他参数,等等。还有一个PEP草案(PEP 632,associated discussion),建议distutils
可能会被弃用,然后在将来的Python 3版本中删除。
答案 4 :(得分:0)
我的简单答案。
def get_files_tree(src="src_path"):
req_files = []
for r, d, files in os.walk(src):
for file in files:
src_file = os.path.join(r, file)
src_file = src_file.replace('\\', '/')
if src_file.endswith('.db'):
continue
req_files.append(src_file)
return req_files
def copy_tree_force(src_path="",dest_path=""):
"""
make sure that all the paths has correct slash characters.
"""
for cf in get_files_tree(src=src_path):
df= cf.replace(src_path, dest_path)
if not os.path.exists(os.path.dirname(df)):
os.makedirs(os.path.dirname(df))
shutil.copy2(cf, df)