shutil.copytree without files
Asked Answered
P

6

13

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?

Potman answered 27/3, 2013 at 16:12 Comment(0)
E
20

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)

Edytheee answered 27/3, 2013 at 16:35 Comment(1)
to avoid errors on dangling symlinks that point to files, you could use set(path for path in files if not os.path.isdir(...)) instead. As a less effective alternative to ignore option, copy_function=lambda *a, *kw: None could be used to disable file copying in Python 3.2+.Veedis
V
2

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)
Veedis answered 27/3, 2013 at 17:30 Comment(0)
G
1

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.

Garniture answered 27/3, 2013 at 16:18 Comment(0)
Q
1

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)
Quanta answered 27/3, 2013 at 16:40 Comment(0)
I
1

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.

Isobel answered 11/5, 2015 at 18:19 Comment(0)
L
0

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/
Luwian answered 14/8, 2021 at 12:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.