Как скопировать весь каталог файлов в существующий каталог с помощью Python?

Запустите следующий код из каталога, который содержит каталог с именем bar (содержащий один или несколько файлов) и каталог с именем baz (также содержащий один или несколько файлов). Убедитесь, что нет каталога с именем foo.

import shutil
shutil.copytree('bar', 'foo')
shutil.copytree('baz', 'foo')

Это не удастся с:

$ python copytree_test.py 
Traceback (most recent call last):
  File "copytree_test.py", line 5, in <module>
    shutil.copytree('baz', 'foo')
  File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/shutil.py", line 110, in copytree
  File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/os.py", line 172, in makedirs
OSError: [Errno 17] File exists: 'foo'

Я хочу, чтобы это работало так же, как если бы я набрал:

$ mkdir foo
$ cp bar/* foo/
$ cp baz/* foo/

Нужно ли мне использовать shutil.copy() для копирования каждого файла из baz в foo? (После того, как я уже скопировал содержимое 'bar' в 'foo' с помощью shutil.copytree()?) Или есть более простой / лучший способ?


person Daryl Spitzer    schedule 08.12.2009    source источник
comment
К вашему сведению: здесь - это исходная функция дерева копирования, просто скопируйте и залатайте :)   -  person schlamar    schedule 17.11.2012
comment
Существует проблема Python, связанная с изменением поведения shutil.copytree(), чтобы разрешить запись в существующий каталог, но есть некоторые особенности детали, которые необходимо согласовать.   -  person Nick Chammas    schedule 11.12.2015
comment
Просто отмечу, что упомянутый выше запрос на улучшение был реализован для Python 3.8: docs.python .org / 3.8 / whatsnew / 3.8.html # shutil   -  person ncoghlan    schedule 17.09.2019


Ответы (14)


Это ограничение стандарта shutil.copytree кажется произвольным и раздражающим. Обходной путь:

import os, shutil
def copytree(src, dst, symlinks=False, ignore=None):
    for item in os.listdir(src):
        s = os.path.join(src, item)
        d = os.path.join(dst, item)
        if os.path.isdir(s):
            shutil.copytree(s, d, symlinks, ignore)
        else:
            shutil.copy2(s, d)

Обратите внимание, что это не совсем соответствует стандарту copytree:

  • он не учитывает параметры symlinks и ignore для корневого каталога дерева src;
  • он не вызывает shutil.Error ошибок на корневом уровне src;
  • в случае ошибок при копировании поддерева, оно будет поднимать shutil.Error для этого поддерева вместо того, чтобы пытаться скопировать другие поддеревья и поднимать единичные комбинированные shutil.Error.
person atzz    schedule 20.09.2012
comment
Спасибо! Согласитесь, это кажется совершенно произвольным! shutil.copytree делает os.makedirs(dst) в начале. Никакая часть кода на самом деле не будет иметь проблем с уже существующим каталогом. Это нужно изменить. По крайней мере, укажите параметр exist_ok=False для вызова - person cfi; 26.09.2012
comment
это дает мне ошибку разрешения errno [13], отказано, какие-либо предложения? - person Drewdin; 13.02.2013
comment
@Drewdin - гм, вы проверяли разрешения для пути к файловой системе из исключения? - person atzz; 14.02.2013
comment
Я сделал, я действительно обнаружил, что у меня есть ошибка в моем коде. у меня был мой d в копировальном дереве, установленный на dst. Это не понравилось. Спасибо за помощь! +1 - person Drewdin; 14.02.2013
comment
Это хороший ответ, однако ответ Митала Вора, приведенный ниже, также заслуживает внимания. Они вызвали copytree рекурсивно, а не вызов shutil.copytree (), потому что в противном случае возникнет та же проблема. Возможно, рассмотрите возможность объединения ответов или обновления Митала Вора. - person PJeffes; 17.10.2013
comment
Это не удается, если задан путь, включающий каталог, который не пуст в месте назначения. Возможно, кто-нибудь сможет решить эту проблему с помощью хвостовой рекурсии, но вот модификация вашего кода, которая работает def copyTree( src, dst, symlinks=False, ignore=None): for item in os.listdir(src): s = os.path.join(src, item) d = os.path.join(dst, item) if os.path.isdir(s): if os.path.isdir(d): self.recursiveCopyTree(s, d, symlinks, ignore) else: shutil.copytree(s, d, symlinks, ignore) else: shutil.copy2(s, d) - person Sojurn; 06.05.2015
comment
Извините за это, проклятый раздел комментариев не очень гибкий, и я даже столкнулся с ограничением символов, поэтому я не мог четко объяснить, что происходит. - person Sojurn; 06.05.2015
comment
Мех, супер-раздражает. Прошло 4 года, а shutil.copytree все еще имеет это глупое ограничение. :-( - person antred; 05.04.2016
comment
@antred ... но distutils.dir_util.copy_tree(), который также находится в stdlib, не имеет такого ограничения и фактически ведет себя так, как ожидалось. Учитывая это, нет веских причин для попытки развернуть вашу собственную (... обычно неработающую) реализацию. Брендана Абеля ответ должен быть сейчас абсолютно принятым решением. - person Cecil Curry; 27.07.2017
comment
Обратите внимание, что copy2 (см. исходный код) и, следовательно, _ 2_ (см. исходный код) не работает, если скопированный каталог содержит специальные файлы (например, именованные каналы). - person patryk.beza; 05.08.2017
comment
Эта функция просто перемещает проблему с верхнего уровня на уровень подкаталогов. Если мы копируем /foo в /bar и /bar существует, тогда это круто, но если есть /foo/subdir/ и /bar/subdir/, то это задохнется. - person Kaz; 03.10.2019
comment
@Kaz абсолютно! И исправление кажется действительно очевидным. Разве мы не можем просто удалить shutil., чтобы дерево копий рекурсивно вызывало себя в случае, если целью является каталог? Нам также нужно добавить первый шаг в функцию mkdir -p к целевому каталогу, чтобы он работал, когда целевой каталог не еще существует. - person TamaMcGlinn; 01.05.2020
comment
годы спустя, и Шутил исправил это! Для всех Python ›= 3.8 есть необязательный параметр dirs_exist_ok - person mckennab; 15.12.2020

Вот решение, входящее в стандартную библиотеку:

from distutils.dir_util import copy_tree
copy_tree("/a/b/c", "/x/y/z")

См. Этот аналогичный вопрос.

Скопируйте содержимое каталога в каталог с помощью Python

person Brendan Abel    schedule 24.06.2015
comment
Это хороший вариант, потому что он использует стандартную библиотеку. Также могут быть сохранены символические ссылки, режим и время. - person itsafire; 28.07.2016
comment
Заметил небольшой недостаток. distutils.errors.DistutilsInternalError: mkpath: 'name' must be a string, т.е. не принимает PosixPath. Нужно str(PosixPath). Список желаний для улучшения. Помимо этого, я предпочитаю этот ответ. - person Sun Bear; 27.08.2019
comment
@SunBear, да, я думаю, что так будет и с большинством других библиотек, которые принимают пути в виде строк. Я полагаю, что это часть недостатка решения не наследовать объект Path от str, как и большинство предыдущих реализаций объектно-ориентированных объектов пути. - person Brendan Abel; 28.08.2019
comment
Кстати, я обнаружил документально подтвержденный недостаток этой функции. Это задокументировано здесь. Пользователям этой функции рекомендуется знать об этом. - person Sun Bear; 28.08.2019
comment
Хотя технически это общедоступно, обратите внимание, что разработчики distutils прояснили это (та же ссылка, что и @ SunBear's, thx !), что distutils.dir_util.copy_tree() считается деталью реализации distutils и не рекомендуется для публичного использования. Реальное решение должно заключаться в том, чтобы shutil.copytree() был улучшен / расширен, чтобы вести себя как distutils.dir_util.copy_tree(), но без его недостатков. А пока я буду продолжать использовать настраиваемые вспомогательные функции, аналогичные некоторым из тех, что указаны в других ответах. - person Boris Dalstein; 26.09.2019
comment
distutils copy_tree (в Python 3.6.5) запутывается символическими ссылками на каталоги. Если ему сказано сохранить символические ссылки в качестве обходного пути для этого, он жалуется всякий раз, когда символическая ссылка уже существует, даже если она перезаписывает обычные существующие файлы. Ошибка! - person Kaz; 03.10.2019
comment
distutils.dir_util.copy_tree у меня ошибается. Когда я использую это много раз подряд, например, в модульных тестах, возникает проблема с созданием файлов. Я бы использовал shutil.copy_tree - person Lost Crotchet; 28.06.2020
comment
К сожалению, это не помогает игнорировать шаблон. - person Digital_Reality; 30.07.2020

Небольшое улучшение в ответе atzz на функцию, в которой вышеуказанная функция всегда пытается скопировать файлы из источника в место назначения.

def copytree(src, dst, symlinks=False, ignore=None):
    if not os.path.exists(dst):
        os.makedirs(dst)
    for item in os.listdir(src):
        s = os.path.join(src, item)
        d = os.path.join(dst, item)
        if os.path.isdir(s):
            copytree(s, d, symlinks, ignore)
        else:
            if not os.path.exists(d) or os.stat(s).st_mtime - os.stat(d).st_mtime > 1:
                shutil.copy2(s, d)

В моей реализации выше

  • Создание выходного каталога, если он еще не существует
  • Копирование каталога путем рекурсивного вызова моего собственного метода.
  • Когда мы подходим к фактическому копированию файла, я проверяю, был ли файл изменен, и только мы должны копировать.

Я использую вышеуказанную функцию вместе со сборкой scons. Это очень помогло мне, так как каждый раз, когда я компилирую, мне может не понадобиться копировать весь набор файлов ... а только те файлы, которые были изменены.

person Mital Vora    schedule 11.12.2012
comment
Хорошо, за исключением того, что у вас есть символические ссылки и они игнорируются как аргументы, но они игнорируются. - person Matthew Alpert; 31.10.2013
comment
Стоит отметить, что степень детализации st_mtime может составлять всего 2 секунды в файловых системах FAT docs.python .org / 2 / library / os.html. Используя этот код в контексте, когда обновления происходят в быстрой последовательности, вы можете обнаружить, что переопределения не выполняются. - person dgh; 10.03.2014
comment
Ошибка в предпоследней строке, должна быть: if not os.path.exists(d) or os.stat(s).st_mtime - os.stat(d).st_mtime > 1: - person mpderbec; 18.06.2015

Python 3.8 представил аргумент dirs_exist_ok для _ 2_:

Рекурсивно скопируйте все дерево каталогов с корнем src в каталог с именем dst и верните целевой каталог. dirs_exist_ok указывает, вызывать ли исключение в случае, если dst или какой-либо отсутствующий родительский каталог уже существует.

Следовательно, с Python 3.8+ это должно работать:

import shutil

shutil.copytree('bar', 'foo')
shutil.copytree('baz', 'foo', dirs_exist_ok=True)
person Chris    schedule 18.11.2019
comment
dirs_exist_ok=False по умолчанию в копировальном дереве, не завершится ли первая попытка копирования? - person Jay; 28.05.2020
comment
@Jay, только если каталог уже существует. Я исключил dirs_exist_ok из первого вызова, чтобы проиллюстрировать разницу (и потому, что каталог еще не существует в примере OP), но, конечно, вы можете использовать его, если хотите. - person Chris; 28.05.2020
comment
Спасибо, если вы добавите комментарий рядом с первым экземпляром, думаю, так будет понятнее :) - person Jay; 28.05.2020
comment
это также работает с pathlib.Path объектами в качестве аргументов src и dst :) copy_tree distutils.dir_util, с другой стороны, требует преобразования в строку. - person MrFuppes; 13.01.2021
comment
Это намного чище, чем старые решения, и должен быть принятым ответом. - person Gavin Uberti; 14.07.2021

Слияние, вдохновленное atzz и Mital Vora:

#!/usr/bin/python
import os
import shutil
import stat
def copytree(src, dst, symlinks = False, ignore = None):
  if not os.path.exists(dst):
    os.makedirs(dst)
    shutil.copystat(src, dst)
  lst = os.listdir(src)
  if ignore:
    excl = ignore(src, lst)
    lst = [x for x in lst if x not in excl]
  for item in lst:
    s = os.path.join(src, item)
    d = os.path.join(dst, item)
    if symlinks and os.path.islink(s):
      if os.path.lexists(d):
        os.remove(d)
      os.symlink(os.readlink(s), d)
      try:
        st = os.lstat(s)
        mode = stat.S_IMODE(st.st_mode)
        os.lchmod(d, mode)
      except:
        pass # lchmod not available
    elif os.path.isdir(s):
      copytree(s, d, symlinks, ignore)
    else:
      shutil.copy2(s, d)
  • То же поведение, что и shutil.copytree, с параметрами символические ссылки и игнорировать.
  • Создать структуру назначения каталога, если она не существует
  • Не завершится, если dst уже существует
person Cyrille Pontvieux    schedule 11.03.2014
comment
Это намного быстрее, чем исходное решение, когда каталоги вложены глубоко. Спасибо - person Kashif; 19.03.2015
comment
Определяли ли вы функцию, также называемую «игнорировать», в другом месте кода? - person KenV99; 12.02.2016
comment
Вы можете определить любую функцию с любым именем перед вызовом функции copytree. Эта функция (которая также может быть лямбда-выражением) принимает два аргумента: имя каталога и файлы в нем, она должна возвращать итерацию игнорируемых файлов. - person Cyrille Pontvieux; 12.02.2016
comment
[x for x in lst if x not in excl] это не то же самое, что дерево копий, которое использует сопоставление с шаблоном глобуса. en.wikipedia.org/wiki/Glob_(programming) - person Konstantin Schubert; 27.05.2016
comment
Нет, он делает то, что docs.python.org/2/library/shutil. html # shutil.copytree делает. Вы смешиваете с docs.python.org/2/library/shutil .html # shutil.ignore_patterns функция - person Cyrille Pontvieux; 27.05.2016
comment
Отлично. В приведенном выше ответе игнорирование использовалось неправильно. - person Keith Holliday; 08.07.2016

в документах явно указано, что целевой каталог не существовать :

Целевой каталог, названный dst, еще не должен существовать; он будет создан вместе с отсутствующими родительскими каталогами.

Я думаю, вам лучше всего os.walk второй и все последующие каталоги, _3 _ каталог и файлы и сделайте дополнительные copystat для каталогов. В конце концов, это именно то, что делает copytree, как описано в документации. Или вы можете copy и copystat каждый каталог / файл и os.listdir вместо os.walk.

person SilentGhost    schedule 08.12.2009

Это вдохновлено оригинальным лучшим ответом, предоставленным atzz, я просто добавил логику замены файла / папки. Таким образом, он фактически не объединяется, а удаляет существующий файл / папку и копирует новый:

import shutil
import os
def copytree(src, dst, symlinks=False, ignore=None):
    for item in os.listdir(src):
        s = os.path.join(src, item)
        d = os.path.join(dst, item)
        if os.path.exists(d):
            try:
                shutil.rmtree(d)
            except Exception as e:
                print e
                os.unlink(d)
        if os.path.isdir(s):
            shutil.copytree(s, d, symlinks, ignore)
        else:
            shutil.copy2(s, d)
    #shutil.rmtree(src)

Раскомментируйте rmtree, чтобы сделать его функцией перемещения.

person radtek    schedule 27.11.2014

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

import shutil
import os


def _copytree(src, dst, symlinks=False, ignore=None):
    """
    This is an improved version of shutil.copytree which allows writing to
    existing folders and does not overwrite existing files but instead appends
    a ~1 to the file name and adds it to the destination path.
    """

    names = os.listdir(src)
    if ignore is not None:
        ignored_names = ignore(src, names)
    else:
        ignored_names = set()

    if not os.path.exists(dst):
        os.makedirs(dst)
        shutil.copystat(src, dst)
    errors = []
    for name in names:
        if name in ignored_names:
            continue
        srcname = os.path.join(src, name)
        dstname = os.path.join(dst, name)
        i = 1
        while os.path.exists(dstname) and not os.path.isdir(dstname):
            parts = name.split('.')
            file_name = ''
            file_extension = parts[-1]
            # make a new file name inserting ~1 between name and extension
            for j in range(len(parts)-1):
                file_name += parts[j]
                if j < len(parts)-2:
                    file_name += '.'
            suffix = file_name + '~' + str(i) + '.' + file_extension
            dstname = os.path.join(dst, suffix)
            i+=1
        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:
                shutil.copy2(srcname, dstname)
        except (IOError, os.error) as why:
            errors.append((srcname, dstname, str(why)))
        # catch the Error from the recursive copytree so that we can
        # continue with other files
        except BaseException as err:
            errors.extend(err.args[0])
    try:
        shutil.copystat(src, dst)
    except WindowsError:
        # can't copy file access times on Windows
        pass
    except OSError as why:
        errors.extend((src, dst, str(why)))
    if errors:
        raise BaseException(errors)
person James    schedule 14.11.2017

Вот версия, которая ожидает pathlib.Path в качестве входных данных.

# Recusively copies the content of the directory src to the directory dst.
# If dst doesn't exist, it is created, together with all missing parent directories.
# If a file from src already exists in dst, the file in dst is overwritten.
# Files already existing in dst which don't exist in src are preserved.
# Symlinks inside src are copied as symlinks, they are not resolved before copying.
#
def copy_dir(src, dst):
    dst.mkdir(parents=True, exist_ok=True)
    for item in os.listdir(src):
        s = src / item
        d = dst / item
        if s.is_dir():
            copy_dir(s, d)
        else:
            shutil.copy2(str(s), str(d))

Обратите внимание, что для этой функции требуется Python 3.6, который является первой версией Python, в которой os.listdir() поддерживает в качестве входных данных объекты, похожие на пути. Если вам нужна поддержка более ранних версий Python, вы можете заменить listdir(src) на listdir(str(src)).

person Boris Dalstein    schedule 26.09.2019

Вот мой вариант той же задачи:

import os, glob, shutil

def make_dir(path):
    if not os.path.isdir(path):
        os.mkdir(path)


def copy_dir(source_item, destination_item):
    if os.path.isdir(source_item):
        make_dir(destination_item)
        sub_items = glob.glob(source_item + '/*')
        for sub_item in sub_items:
            copy_dir(sub_item, destination_item + '/' + sub_item.split('/')[-1])
    else:
        shutil.copy(source_item, destination_item)
person Barmaley    schedule 28.06.2014

Вот версия, вдохновленная этой веткой, которая более точно имитирует distutils.file_util.copy_file.

updateonly - логическое значение, если True, будут копировать только файлы с датой изменения, более новые, чем существующие файлы в dst, если не указано в forceupdate, которое будет копироваться независимо.

ignore и forceupdate ожидают списков имен файлов или папок / файлов относительно src и принимают подстановочные знаки в стиле Unix, подобные glob или fnmatch.

Функция возвращает список скопированных файлов (или будет скопирован, если dryrun, если True).

import os
import shutil
import fnmatch
import stat
import itertools

def copyToDir(src, dst, updateonly=True, symlinks=True, ignore=None, forceupdate=None, dryrun=False):

    def copySymLink(srclink, destlink):
        if os.path.lexists(destlink):
            os.remove(destlink)
        os.symlink(os.readlink(srclink), destlink)
        try:
            st = os.lstat(srclink)
            mode = stat.S_IMODE(st.st_mode)
            os.lchmod(destlink, mode)
        except OSError:
            pass  # lchmod not available
    fc = []
    if not os.path.exists(dst) and not dryrun:
        os.makedirs(dst)
        shutil.copystat(src, dst)
    if ignore is not None:
        ignorepatterns = [os.path.join(src, *x.split('/')) for x in ignore]
    else:
        ignorepatterns = []
    if forceupdate is not None:
        forceupdatepatterns = [os.path.join(src, *x.split('/')) for x in forceupdate]
    else:
        forceupdatepatterns = []
    srclen = len(src)
    for root, dirs, files in os.walk(src):
        fullsrcfiles = [os.path.join(root, x) for x in files]
        t = root[srclen+1:]
        dstroot = os.path.join(dst, t)
        fulldstfiles = [os.path.join(dstroot, x) for x in files]
        excludefiles = list(itertools.chain.from_iterable([fnmatch.filter(fullsrcfiles, pattern) for pattern in ignorepatterns]))
        forceupdatefiles = list(itertools.chain.from_iterable([fnmatch.filter(fullsrcfiles, pattern) for pattern in forceupdatepatterns]))
        for directory in dirs:
            fullsrcdir = os.path.join(src, directory)
            fulldstdir = os.path.join(dstroot, directory)
            if os.path.islink(fullsrcdir):
                if symlinks and dryrun is False:
                    copySymLink(fullsrcdir, fulldstdir)
            else:
                if not os.path.exists(directory) and dryrun is False:
                    os.makedirs(os.path.join(dst, dir))
                    shutil.copystat(src, dst)
        for s,d in zip(fullsrcfiles, fulldstfiles):
            if s not in excludefiles:
                if updateonly:
                    go = False
                    if os.path.isfile(d):
                        srcdate = os.stat(s).st_mtime
                        dstdate = os.stat(d).st_mtime
                        if srcdate > dstdate:
                            go = True
                    else:
                        go = True
                    if s in forceupdatefiles:
                        go = True
                    if go is True:
                        fc.append(d)
                        if not dryrun:
                            if os.path.islink(s) and symlinks is True:
                                copySymLink(s, d)
                            else:
                                shutil.copy2(s, d)
                else:
                    fc.append(d)
                    if not dryrun:
                        if os.path.islink(s) and symlinks is True:
                            copySymLink(s, d)
                        else:
                            shutil.copy2(s, d)
    return fc
person KenV99    schedule 12.02.2016

В предыдущем решении есть проблема, из-за которой src может перезаписать dst без какого-либо уведомления или исключения.

Я добавляю predict_error метод для прогнозирования ошибок перед копированием. copytree в основном основан на версии Сирилла Понтвье.

Лучше всего сначала использовать predict_error для прогнозирования всех ошибок, если только вы не хотите, чтобы исключения возникали одно за другим при выполнении copytree, пока не будут исправлены все ошибки.

def predict_error(src, dst):  
    if os.path.exists(dst):
        src_isdir = os.path.isdir(src)
        dst_isdir = os.path.isdir(dst)
        if src_isdir and dst_isdir:
            pass
        elif src_isdir and not dst_isdir:
            yield {dst:'src is dir but dst is file.'}
        elif not src_isdir and dst_isdir:
            yield {dst:'src is file but dst is dir.'}
        else:
            yield {dst:'already exists a file with same name in dst'}

    if os.path.isdir(src):
        for item in os.listdir(src):
            s = os.path.join(src, item)
            d = os.path.join(dst, item)
            for e in predict_error(s, d):
                yield e


def copytree(src, dst, symlinks=False, ignore=None, overwrite=False):
    '''
    would overwrite if src and dst are both file
    but would not use folder overwrite file, or viceverse
    '''
    if not overwrite:
        errors = list(predict_error(src, dst))
        if errors:
            raise Exception('copy would overwrite some file, error detail:%s' % errors)

    if not os.path.exists(dst):
        os.makedirs(dst)
        shutil.copystat(src, dst)
    lst = os.listdir(src)
    if ignore:
        excl = ignore(src, lst)
        lst = [x for x in lst if x not in excl]
    for item in lst:
        s = os.path.join(src, item)
        d = os.path.join(dst, item)
        if symlinks and os.path.islink(s):
            if os.path.lexists(d):
                os.remove(d)
            os.symlink(os.readlink(s), d)
            try:
                st = os.lstat(s)
                mode = stat.S_IMODE(st.st_mode)
                os.lchmod(d, mode)
            except:
                pass  # lchmod not available
        elif os.path.isdir(s):
            copytree(s, d, symlinks, ignore)
        else:
            if not overwrite:
                if os.path.exists(d):
                    continue
            shutil.copy2(s, d)
person Mithril    schedule 13.07.2016

Попробуй это:

import os,shutil

def copydir(src, dst):
  h = os.getcwd()
  src = r"{}".format(src)
  if not os.path.isdir(dst):
     print("\n[!] No Such directory: ["+dst+"] !!!")
     exit(1)

  if not os.path.isdir(src):
     print("\n[!] No Such directory: ["+src+"] !!!")
     exit(1)
  if "\\" in src:
     c = "\\"
     tsrc = src.split("\\")[-1:][0]
  else:
    c = "/"
    tsrc = src.split("/")[-1:][0]

  os.chdir(dst)
  if os.path.isdir(tsrc):
    print("\n[!] The Directory Is already exists !!!")
    exit(1)
  try:
    os.mkdir(tsrc)
  except WindowsError:
    print("\n[!] Error: In[ {} ]\nPlease Check Your Dirctory Path !!!".format(src))
    exit(1)
  os.chdir(h)
  files = []
  for i in os.listdir(src):
    files.append(src+c+i)
  if len(files) > 0:
    for i in files:
        if not os.path.isdir(i):
            shutil.copy2(i, dst+c+tsrc)

  print("\n[*] Done ! :)")

copydir("c:\folder1", "c:\folder2")
person Ahmed    schedule 06.12.2018

Я бы предположил, что самый быстрый и простой способ - заставить python вызывать системные команды ...

пример..

import os
cmd = '<command line call>'
os.system(cmd)

Tar и gzip up каталог .... распаковать и распаковать каталог в желаемое место.

да?

person Kirby    schedule 08.12.2009
comment
если вы работаете в Windows ... скачайте 7zip ... и используйте для этого командную строку. ... снова просто предложения. - person Kirby; 08.12.2009
comment
Системные команды всегда должны использоваться в крайнем случае. Всегда лучше использовать стандартную библиотеку, когда это возможно, чтобы ваш код был переносимым. - person jathanism; 08.12.2009
comment
Не зависит от системы, требует дополнительного места и времени процессора для сжатия и извлечения, определенно не лучшая идея. - person Danny Varod; 09.03.2021