复制和合并目录,不包括某些扩展名

时间:2016-08-10 14:56:12

标签: python windows copy-paste

我想将具有相同结构的多个目录(子目录具有相同的名称)但不同的内容复制到第三个位置并合并它们。同时,我想忽略某些文件扩展名而不是复制它们。

我发现copy_tree()库中的distutils.dir_util函数可以轻松处理第一个任务。这里的问题是copy_tree()不能忽略文件;它只是复制一切..

  

distutils.dir_util.copy_tree() - 示例

dirs_to_copy = [r'J:\Data\Folder_A', r'J:\Data\Folder_B']
destination_dir = r'J:\Data\DestinationFolder'
for files in dirs_to_copy:
    distutils.dir_util.copy_tree(files, destination_dir)
    # succeeds in merging sub-directories but copies everything.
    # Due to time constrains, this is not an option.

对于第二项任务(使用“排除文件”选项进行复制),这次copytree()库中存在shutil函数。现在的问题是它无法合并文件夹,因为目标目录不能存在..

  

shutil.copytree() - 示例

dirs_to_copy = [r'J:\Data\Folder_A', r'J:\Data\Folder_B']
destination_dir = r'J:\Data\DestinationFolder'
for files in dirs_to_copy:
    shutil.copytree(files, destination_dir, ignore=shutil.ignore_patterns("*.abc"))
    # successfully ignores files with "abc" extensions but fails 
    # at the second iteration since "Destination" folder exists..

有什么能提供两全其美的东西,还是我必须自己编码呢?

2 个答案:

答案 0 :(得分:3)

正如 PeterBrittain 建议的那样,编写我自己的shutil.copytree()版本是可行的方法。下面是代码。请注意,唯一的区别是在os.makedirs()块中包裹if

from shutil import copy2, copystat, Error, ignore_patterns
import os


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

    # -------- E D I T --------
    # os.path.isdir(dst)
    if not os.path.isdir(dst):
        os.makedirs(dst)
    # -------- E D I T --------

    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_multi(srcname, dstname, symlinks, ignore)
            else:
                copy2(srcname, dstname)
        except (IOError, os.error) as why:
            errors.append((srcname, dstname, str(why)))
        except Error as err:
            errors.extend(err.args[0])
    try:
        copystat(src, dst)
    except WindowsError:
        pass
    except OSError as why:
        errors.extend((src, dst, str(why)))
    if errors:
        raise Error(errors)

答案 1 :(得分:0)

如果你想直接使用shutil,这是os.makedirs的一个热补丁,可以跳过错误。

import os
os_makedirs = os.makedirs
def safe_makedirs(name, mode=0777):
    if not os.path.exists(name):
        os_makedirs(name, mode)
os.makedirs = safe_makedirs

import shutil

dirs_to_copy = [r'J:\Data\Folder_A', r'J:\Data\Folder_B']
destination_dir = r'J:\Data\DestinationFolder'
if os.path.exists(destination_dir):
    shutil.rmtree(destination_dir)
for files in dirs_to_copy:
    shutil.copytree(files, destination_dir, ignore=shutil.ignore_patterns("*.abc")) code here