Вопрос

I'm trying use shutil.copytree:

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

This copy also files in folder. I need copy only folders without ANY files. How to do it?

Это было полезно?

Решение

You can do that by providing a "ignore" function

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)

Basically, when you call copytree, it will recursively go to each child folder and provide a list of files in that folder to the ignore function to check if those files are suitable based on a pattern. The ignored files will be returned as a list in the end of the function and then, copytree will only copy items excluding from that list (which in your case, contains all the files in the current folder)

Другие советы

Here's an implementation of @Oz123's solution which is based on 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)

You should consider using os.walk.

Here is an example for os.walk. This way you could list all the directories and then create them with os.mkdir.

use distutils.dir_util.create_tree to just copy directory structure (not files)

note : the argument files is a list of filenames. if you want something that would work as 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)

If you want ignore pattern functionality with os.walk(), then:

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

This will ignore .git directory.

Note: This requires Python >=3.2 as I used the exist_ok option with makedirs which isn't available on older versions.

The above answers work, but they certainly won't be hassle-free, and could easily cost you 30 minutes. If you're using Windows, the quickest method is to open the shell and use xcopy, i.e.:

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

Alternatively, if you run Linux, you can use

rsync -a -f"+ */" -f"- *" source/ destination/
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top