Скопируйте файл или каталоги рекурсивно в Python

У Python есть функции для копирования файлов (например, shutil.copy) и функций для копирования каталогов (например, shutil.copytree), но я не нашел никакой функции, которая обрабатывает оба. Конечно, тривиально проверить, хотите ли вы скопировать файл или каталог, но это похоже на странное упущение.

Нет ли стандартной функции, которая работает как команда unix cp -r, т.е. рекурсивно поддерживает как каталоги, так и файлы и копии? Какой был бы самый элегантный способ обойти эту проблему в Python?

Ответ 1

Я предлагаю вам сначала вызвать shutil.copytree, и если вызывается исключение, повторите попытку с shutil.copy.

import shutil, errno

def copyanything(src, dst):
    try:
        shutil.copytree(src, dst)
    except OSError as exc: # python >2.5
        if exc.errno == errno.ENOTDIR:
            shutil.copy(src, dst)
        else: raise

Ответ 2

Unix cp не поддерживает обе каталоги и файлы:

betelgeuse:tmp james$ cp source/ dest/
cp: source/ is a directory (not copied).

Чтобы сделать cp скопировать каталог, вам нужно вручную указать cp, что это каталог, используя флаг '-r'.

Здесь есть некоторая отключаемость - cp -r при передаче имени файла, так как источник с радостью копирует только один файл; copytree не будет.

Ответ 3

Чтобы добавить в Tzot и gns ответы, здесь альтернативный способ копирования файлов и папок рекурсивно. (Python 3.X)

import os, shutil

root_src_dir = r'C:\MyMusic'    #Path/Location of the source directory
root_dst_dir = 'D:MusicBackUp'  #Path to the destination folder

for src_dir, dirs, files in os.walk(root_src_dir):
    dst_dir = src_dir.replace(root_src_dir, root_dst_dir, 1)
    if not os.path.exists(dst_dir):
        os.makedirs(dst_dir)
    for file_ in files:
        src_file = os.path.join(src_dir, file_)
        dst_file = os.path.join(dst_dir, file_)
        if os.path.exists(dst_file):
            os.remove(dst_file)
        shutil.copy(src_file, dst_dir)

Если это ваш первый раз, и вы не знаете, как копировать файлы и папки рекурсивно, я надеюсь, что это поможет.

Ответ 4

shutil.copy и shutil.copy2 - копирование файлов.

shutil.copytree копирует папку со всеми файлами и всеми подпапками. shutil.copytree использует shutil.copy2 для копирования файлов.

Таким образом, аналогом cp -r, который вы говорите, является shutil.copytree, потому что cp -r нацеливает и копирует папку и ее файлы/подпапки, например shutil.copytree. Без -r cp копировать файлы типа shutil.copy и shutil.copy2 do.

Ответ 5

Метод python shutil.copytree - это беспорядок. Я сделал один, который работает правильно:

def copydirectorykut(src, dst):
    os.chdir(dst)
    list=os.listdir(src)
    nom= src+'.txt'
    fitx= open(nom, 'w')

    for item in list:
        fitx.write("%s\n" % item)
    fitx.close()

    f = open(nom,'r')
    for line in f.readlines():
        if "." in line:
            shutil.copy(src+'/'+line[:-1],dst+'/'+line[:-1])
        else:
            if not os.path.exists(dst+'/'+line[:-1]):
                os.makedirs(dst+'/'+line[:-1])
                copydirectorykut(src+'/'+line[:-1],dst+'/'+line[:-1])
            copydirectorykut(src+'/'+line[:-1],dst+'/'+line[:-1])
    f.close()
    os.remove(nom)
    os.chdir('..')