我想在Python中实现cp -r
版本,以特殊方式处理某些目录。如果您执行mycp.py -r indir outdir
,我希望indir
及其所有文件/子目录完全复制到outdir
,但某些文件名除外。在Python中最便携的方法是什么?
示例:我有这个目录结构:
dir1/
file1
dir2/
dir3/
specialdir/
myfile.bar
file1
是一个文件,specialdir
是一个包含文件myfile.bar
的目录。我想复制dir1
及其所有内容,但特别处理其中包含*.bar
个文件的目录。在这种情况下,只有specialdir
符合条件。我希望mycopy
复制所有dir1
,但用自己的压缩版本替换任何特殊目录。在上面的示例中,这意味着按原样复制dir1
,但将specialdir
替换为可能包含处理版specialdir.zip
的{{1}}。
我试图按照下面的建议,但我不知道如何处理复制:
myfile.bar
如果我尝试它,它会正确检测特殊目录:
import os
import shutil
SPECIAL_DIRS = []
def is_special_dir(path, dirnames):
"""directories are special if they have .bar files"""
special_dirs = []
for d in dirnames:
d = os.path.join(path, d)
if os.path.isdir(d):
files_in_d = os.listdir(d)
for f in files_in_d:
if f.endswith(".bar"):
# directory is special if it contains
# .bar files
special_dirs.append(d)
SPECIAL_DIRS.extend(special_dirs)
return special_dirs
def my_copy(indir, outdir):
shutil.copytree(indir, outdir, ignore=is_special_dir)
print "Found special dirs: ", SPECIAL_DIRS
# make a copy of dir1 but handle special directories
# differently
my_copy("dir1", "copy_dir1")
如何在$ copy_test.py
Found special dirs: ['dir1/dir2/specialdir']
的相应位置插入specialdir
?我希望copy_dir1
(目标目录)具有与copy_dir1
(源目录)完全相同的结构,除非对包含dir1
文件的目录进行特殊处理。
答案 0 :(得分:3)
听起来您希望shutil.copytree使用 ignore 参数:
如果给出了 ignore ,它必须是一个可调用的,它将接收
copytree()
访问的目录作为其参数,以及{{1}返回的内容列表}}。由于os.listdir()
是递归调用的,因此对于每个复制的目录,将调用 ignore callable一次。 callable必须返回一系列相对于当前目录的目录和文件名(即第二个参数中的项的子集);这些名称将在复制过程中被忽略。 ' ignore_patterns()'可用于创建一个基于glob样式模式忽略名称的可调用函数。
所以这样的事情应该有效:
copytree()
这是一个例子。简化的忽略函数仍然会创建一个空的特殊目录,但在执行特殊的zip拷贝之前很容易删除。我还嵌套了特殊函数,因此可以多次使用def what_to_ignore(path,names):
if is_special(path):
# process names here returning any or all to ignore
shutil.copytree(indir,outdir,ignore=what_to_ignore)
而不依赖于使用全局变量。拉链是用户的练习:
my_copy
<强>输出强>
import fnmatch
import shutil
import os
def my_copy(indir, outdir):
special = []
def is_special_dir(path, names):
"""directories are special if they have .bar files"""
if fnmatch.filter(names,'*.bar'):
special.append(path)
return names
return []
shutil.copytree(indir, outdir, ignore=is_special_dir)
print('Found special dirs:',special)
for src in special:
rel = os.path.relpath(src,indir)
dst = os.path.join(outdir,rel)
os.rmdir(dst)
print('Zip "{}" to "{}.zip"'.format(src,dst))
my_copy('dir1','dira')
my_copy('dir1','dirb')