如何在python中递归复制目录并覆盖所有?

IAm*_*aja 62 python distutils copy

我正在尝试将/home/myUser/dir1/其所有内容(及其内容等)复制到/home/myuser/dir2/python中.此外,我希望副本覆盖所有内容dir2/.

看起来distutils.dir_util.copy_tree可能是这个职位的合适的工具,但不能肯定是否有什么更容易/更明显,使用这样一个简单的任务.

如果它是正确的工具,我该如何使用它?根据文档,它需要8个参数.我必须通过所有8只src,dst并且update,如果是这样,怎么样(我全新到Python).

如果有更好的东西,有人可以给我一个例子并指出我正确的方向吗?提前致谢!

Vic*_*ent 59

你可以用distutils.dir_util.copy_tree.它工作得很好,你不必通过每次吵架,只有srcdst是强制性的.

但是在您的情况下,您不能使用类似的工具,shutil.copytree因为它的行为不同:由于目标目录不能存在,因此该函数不能用于覆盖其内容.

如果您想cp按照问题中的建议使用该工具,请注意目前使用该subprocess模块是产生新进程的推荐方法,您可以在os.system函数文档中看到.

  • 是不是“distutils”已被弃用,还是只支持“setup.py”中的“setuptools”? (6认同)
  • `shutil` 和 `distutils.dir_util` 之间的逻辑/哲学区别是什么?一般来说,一种比另一种更可取吗? (2认同)

Mic*_*ael 31

看一看的shutil包,特别是rmtreecopytree.您可以检查文件/路径是否存在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)
Run Code Online (Sandbox Code Playgroud)

copytree如果dirs已经存在,Vincent是不对的.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
Run Code Online (Sandbox Code Playgroud)

  • 您的示例不会覆盖任何内容,只需将一个目录替换为另一个目录即可。据我所知,替换内容和覆盖内容是不同的事情。该问题特别要求覆盖。 (3认同)
  • `shutil.copytree`应该不起作用; 如果确实如此,这是一个错误,因为它的文档说"目标目录,由*dst*命名,必须不存在". (2认同)

mgr*_*ant 21

这是一个简单的解决方案,用源递归覆盖目标,随时创建任何必要的目录.这不会处理符号链接,但它将是一个简单的扩展(请参阅上面的@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)
Run Code Online (Sandbox Code Playgroud)

  • @mgrant你有*不知道你救了我多少时间.++ (2认同)

ort*_*sol 12

在 Python 3.8 中,dirs_exist_ok关键字参数被添加shutil.copytree()

dirs_exist_ok指示是否引发异常,以防万一dst或任何丢失的父目录已经存在。

因此,即使目标目录已经存在,以下内容也适用于最新版本的 Python:

shutil.copytree(src, dest, dirs_exist_ok=True)  # 3.8+ only!
Run Code Online (Sandbox Code Playgroud)

一个主要的好处是它比 更灵活distutils.dir_util.copy_tree(),因为它需要忽略文件的其他参数等(请参阅文档)。最重要的是,已接受的PEP 632还声明distutils将在 Python 3 的未来版本中弃用并随后将其删除。