Подтвердить что ты не робот

Как рекурсивно копировать каталог в python и перезаписывать все?

Я пытаюсь скопировать /home/myUser/dir1/ и все его содержимое (и их содержимое и т.д.) в /home/myuser/dir2/ в python. Кроме того, я хочу, чтобы копия перезаписывала все в dir2/.

Похоже, что distutils.dir_util.copy_tree может быть правильным инструментом для задания, но не уверен, что для такой простой задачи есть что-то более простое/более очевидное.

Если это правильный инструмент, как его использовать? Согласно docs имеется 8 параметров. Мне нужно передать все 8 только src, dst и update, и если да, то как (я новичок в Python).

Если что-то там лучше, может ли кто-нибудь дать мне пример и указать мне в правильном направлении? Спасибо заранее!

4b9b3361

Ответ 1

Вы можете использовать distutils.dir_util.copy_tree. Он работает нормально, и вам не нужно передавать каждый аргумент, только src и dst являются обязательными.

Однако в вашем случае вы не можете использовать аналогичный инструмент, например shutil.copytree, потому что он ведет себя по-другому: поскольку каталог назначения не должен существовать, эта функция не может использоваться для перезаписи его содержимого.

Если вы хотите использовать инструмент cp, как предложено в комментариях к вопросу, остерегайтесь, что использование модуля subprocess в настоящее время является рекомендуемым способом для нереста новых процессов, как вы можете видеть в документация функции os.system.

Ответ 2

Взгляните на пакет 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)

Винсент был прав, что copytree не работает, если каталоги уже существуют. Так что distutils - лучшая версия. Ниже приведена исправленная версия shutil.copytree. Он в основном скопировал 1-1, кроме первого os.makedirs(), помещенного за конструкцией if-else:

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

Ответ 3

Здесь простое решение для рекурсивной перезаписи адресата с источником, создающего все необходимые каталоги по мере его появления. Это не обрабатывает символические ссылки, но это будет простое расширение (см. Ответ от @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)

Ответ 4

Вот решение, которое помогло мне в нескольких строках кода:

def overwrite(dir_src, dir_dst):
    for root, dirs, files in os.walk(dir_src):
        for filename in files:
            file_path_src = os.path.join(root, filename)
            # replace the first occurrence of lambdas_src_folder with tmp_folder
            file_path_dst = file_path_src.replace(dir_src, dir_dst, 1)
            # overwrite or create file (https://docs.python.org/2/library/shutil.html#shutil.copy)
            shutil.copy(file_path_src, file_path_dst)