shutil.copytree без файлов

Я пытаюсь использовать shutil.copytree:

shutil.copytree(SOURCE_DIR, TARGET_DIR, ignore=None)

Эта копия также файлы в папке. Мне нужно копировать только папки без каких-либо файлов. Как это сделать?

6 ответов

Решение

Вы можете сделать это, предоставив функцию "игнорировать"

def ig_f(dir, files):
    return [f for f in files if os.path.isfile(os.path.join(dir, f))]

shutil.copytree(SRC, DES, ignore=ig_f)

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

Вот реализация решения @Oz123, которое основано на os.walk():

import os

def create_empty_dirtree(srcdir, dstdir, onerror=None):
    srcdir = os.path.abspath(srcdir)
    srcdir_prefix = len(srcdir) + len(os.path.sep)
    os.makedirs(dstdir)
    for root, dirs, files in os.walk(srcdir, onerror=onerror):
        for dirname in dirs:
            dirpath = os.path.join(dstdir, root[srcdir_prefix:], dirname)
            try:
                os.mkdir(dirpath)
            except OSError as e:
                if onerror is not None:
                    onerror(e)

Использование distutils.dir_util.create_tree просто скопировать структуру каталогов (не файлов)

примечание: аргумент files список имен файлов если вы хотите что-то, что будет работать как shutils.copytree:

import os
import distutils.dir_util
def copy_tree(source, dest, **kwargs):
    filenames = [os.path.join(path, file_) for path, _, files in os.walk(source) for file_ in files]
    distutils.dir_util.create_tree(dest, filenames, **kwargs)

Вы должны рассмотреть возможность использования os.walk,

Вот пример для os.walk. Таким образом, вы можете перечислить все каталоги, а затем создать их с os.mkdir,

Если вы хотите игнорировать функциональность шаблона с os.walk(), затем:

ignorePatterns=[".git"]
def create_empty_dirtree(src, dest, onerror=None):
    src = os.path.abspath(src)
    src_prefix = len(src) + len(os.path.sep)
    for root, dirs, files in os.walk(src, onerror=onerror):
        for pattern in ignorePatterns:
            if pattern in root:
                break
        else:
            #If the above break didn't work, this part will be executed
            for dirname in dirs:
                for pattern in ignorePatterns:
                    if pattern in dirname:
                        break
                else:
                    #If the above break didn't work, this part will be executed
                    dirpath = os.path.join(dest, root[src_prefix:], dirname)
                    try:
                        os.makedirs(dirpath,exist_ok=True)
                    except OSError as e:
                        if onerror is not None:
                            onerror(e)
                continue;#If the above else didn't executed, this will be reached

        continue;#If the above else didn't executed, this will be reached

Это будет игнорировать .git каталог.

Примечание: это требует Python >=3.2 как я использовал exist_ok вариант с makedirs который недоступен в старых версиях.

Приведенные выше ответы работают, но они определенно не дадут вам никаких хлопот и могут легко стоить вам 30 минут. Если вы используете Windows, самый быстрый способ - открыть оболочку и использовать xcopy, то есть:

      c:\user> xcopy "source" "destination" /t /e

В качестве альтернативы, если вы используете Linux, вы можете использовать

      rsync -a -f"+ */" -f"- *" source/ destination/
Другие вопросы по тегам