将特定文件复制到新文件夹,同时保留原始子目录树 [英] Copying specific files to a new folder, while maintaining the original subdirectory tree

查看:115
本文介绍了将特定文件复制到新文件夹,同时保留原始子目录树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个很大的目录,其中包含许多我要排序的子目录,我正在尝试将特定的文件类型复制到一个新文件夹中,但是我想保留原始的子目录。

I have a large directory with many subdirectories that I am trying to sort, I am trying to copy specific file types to a new folder, but I want to maintain the original subdirectories.

def copyFile(src, dest):
try:
    shutil.copy(src,dest)
except shutil.Error as e:
    print('Error: %s' % e)
except IOError as e:
    print('Error: %s' % s.strerror)


for root, directories, files in os.walk(directory):
    for directoryname in directories:
        dirpath = os.path.join(root,directoryname)
        dir_paths.append(dirpath)
        dir_names.append(directoryname)

        if not os.listdir(dirpath): #Cheching if directory is empty
            print("Empty")
            EmptyDirs.append(directoryname) #Add directory name to empty directory list
            EmptyDirPath.append(dirpath)
        else:
            pass

    for filename in files:
        filepath = os.path.join(root,filename)
        file_paths.append(filepath)
        file_names.append(filename)

    if filename.lower().endswith(".sldasm"):
            print(filename.encode('utf8'))
            SolidModels.append(filename)
            copyFile(filepath,dest)
    elif filename.lower().endswith(".sldprt"):
            print(filename.encode('utf8'))
            SolidModels.append(filename)
            copyFile(filepath,dest)
    else:
        pass

这是我现在使用的代码,但是它只是复制文件而没有复制它们原来所在的子目录,因此它们在新文件夹中完全没有组织。

This is the code I am using now, but it just copies the files without copying the subdirectories they were originally in, so they are completely unorganized in the new folder.

这是使用copytree的新代码,但是现在特定文件将不会复制,

This is the new code using copytree, however now the specific files will not copy, only the subdirectories do.

def copytree(src, dst, symlinks=False, ignore=None):
    names = os.listdir(src)
    if ignore is not None:
        ignored_names = ignore(src, names)
    else:
        ignored_names = set()

os.makedirs(dst)
errors = []

for name in names:
    if name in ignored_names:
        continue

    srcname = os.path.join(src, name)
    dstname = os.path.join(dst, name)

    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:
            if src is "*.sldasm":
                copy2(srcname, dstname)
            elif src is "*.sldprt":
                copy2(srcname, dstname)

    except (IOError, os.error) as why:
            errors.append((srcname, dstname, str(why)))


推荐答案

您可以做自己想做的事情内置 shutil.copytree() 函数,方法是使用(滥用?)其可选的 ignore 关键字参数。棘手的是,如果给定的话,它必须是一个可调用的函数,它返回在每个目录中应复制的内容,而不是应复制的内容。

You can do what you want with the built-in shutil.copytree() function by using (abusing?) its optional ignore keyword argument. The tricky part is that, if given, it must be a callable that returns what, in each directory, should not be copied, rather than what should be.

但是可以编写类似于 shutil.ignore_patterns() 创建一个执行所需功能的函数,并将其用作 ignore 关键字

However it possible to write a factory function similar to shutil.ignore_patterns() that creates a function that does what's needed, and use that as the ignore keyword argument's value.

首先返回的函数通过 fnmatch.filter() 函数,然后从给定的所有内容列表中将其删除目录,除非它们是子目录名称,否则将保留它们供以后[递归]处理。 (这就是使它复制整个树的原因,而您尝试编写自己的 copytree()函数可能是错误的)。

The function returned first determines what files to keep via the fnmatch.filter() function, then removes them from the list of everything which is in the given directory, unless they're a sub-directory name, in which case they're left in for later [recursive] processing. (This is what makes it copy the whole tree and what was probably wrong with your attempt to write your own copytree() function).

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Works in Python 2.7 & 3.x

import fnmatch
from os.path import isdir, join

def include_patterns(*patterns):
    """ Function that can be used as shutil.copytree() ignore parameter that
    determines which files *not* to ignore, the inverse of "normal" usage.

    This is a factory function that creates a function which can be used as a
    callable for copytree()'s ignore argument, *not* ignoring files that match
    any of the glob-style patterns provided.

    ‛patterns’ are a sequence of pattern strings used to identify the files to
    include when copying the directory tree.

    Example usage:

        copytree(src_directory, dst_directory,
                 ignore=include_patterns('*.sldasm', '*.sldprt'))
    """
    def _ignore_patterns(path, all_names):
        # Determine names which match one or more patterns (that shouldn't be
        # ignored).
        keep = (name for pattern in patterns
                        for name in fnmatch.filter(all_names, pattern))
        # Ignore file names which *didn't* match any of the patterns given that
        # aren't directory names.
        dir_names = (name for name in all_names if isdir(join(path, name)))
        return set(all_names) - set(keep) - set(dir_names)

    return _ignore_patterns


if __name__ == '__main__':

    from shutil import copytree, rmtree
    import os

    src = r'C:\vols\Files\PythonLib\Stack Overflow'
    dst = r'C:\vols\Temp\temp\test'

    # Make sure the destination folder does not exist.
    if os.path.exists(dst) and os.path.isdir(dst):
        print('removing existing directory "{}"'.format(dst))
        rmtree(dst, ignore_errors=False)

    copytree(src, dst, ignore=include_patterns('*.png', '*.gif'))

    print('done')

这篇关于将特定文件复制到新文件夹,同时保留原始子目录树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆