![](/img/trans.png)
[英]Deleting all files and directories except a few specified in a “list” in python
[英]Delete all files/directories except two specific directories
所以,似乎有一些问题要求删除匹配某些情况的文件/目录,但我正在寻找完全相反的:删除与我提供的示例不匹配的文件夹中的所有内容。
例如,这是一个示例目录树:
.
|-- coke
| |-- diet
| |-- regular
| `-- vanilla
|-- icecream
| |-- chocolate
| |-- cookiedough
| |-- cupcake
| | |-- file1.txt
| | |-- file2.txt
| | |-- file3.txt
| | |-- file4.txt
| | `-- file5.txt
| `-- vanilla
|-- lol.txt
|-- mtndew
| |-- classic
| |-- codered
| |-- livewire
| | |-- file1.txt
| | |-- file2.txt
| | |-- file3.txt
| | |-- file4.txt
| | `-- file5.txt
| `-- throwback
`-- pepsi
|-- blue
|-- classic
|-- diet
`-- throwback
我想删除test / icecream / cupcake /和test / mtndew / livewire /中的文件。 其他一切都可以,包括目录结构。 那么,我怎样才能做到这一点? 我不介意的语言:bash或python。
此命令将只在原始目录中保留所需的文件:
find test \( ! -path "test/mtndew/livewire/*" ! -path "test/icecream/cupcake/*" \) -delete
不需要cpio。 它适用于Ubuntu,Debian 5和Mac OS X.
在Linux上,它将报告它无法删除非空目录,这正是所需的结果。 在Mac OS X上,它会悄悄地做正确的事情。
“除了”之外的一切都是为什么我们有if语句; 以及为什么os.walk的目录列表是一个可变列表。
for path, dirs, files in os.walk( 'root' ):
if 'coke' in dirs:
dirs.remove('coke')
dirs.remove('pepsi')
find
's -prune
,但让它适用于特定的路径( icecream/cupcake/
)而不是特定的目录( cupcake/
)是很痛苦的。
就个人而言,我只是使用cpio
和硬链接(以避免必须复制它们)要保留到新树的目录中的文件,然后删除旧的:
find test -path 'test/icecream/cupcake/*' -o -path 'test/mtndew/livewire/*' | cpio -padluv test-keep
rm -rf test
这也将保留您打算保留的目录的现有目录结构。
find /path/to/test/ -depth -mindepth 1 \
! -path "/path/to/test/icecream/cupcake/*" \
! -path "/path/to/test/icecream/cupcake" \
! -path "/path/to/test/icecream" \
! -path "/path/to/test/mtndew/livewire/*" \
! -path "/path/to/test/mtndew/livewire" \
! -path "/path/to/test/mtndew"
-delete -print
编写所有要保留的路径有点单调乏味,但这是单独使用find的唯一方法。
你可以根据Python的os.walk函数做一些事情:
import os
for root, dirs, files in os.walk(top, topdown=False):
for name in files:
os.remove(os.path.join(root, name))
for name in dirs:
os.rmdir(os.path.join(root, name))
...只是添加一些东西来忽略你感兴趣的路径。
将要保留的内容移动到其他位置,然后删除剩下的内容。
解决问题的oneliner:
找 。 | grep -v“test / icecream / cupcake /”| grep -v“test / mtndew / livewire /”| xargs rm -r
删除,因为它不起作用
如果文件名中包含空格,这可能会让您遇到麻烦,如果有其他树匹配模式,它可能会保留更多文件。
一个更好的解决方案:
find . |sed "s/.*/rm '&'/"|grep -v "rm './test/icecream/cupcake/"| grep -v "rm './test/mtndew/livewire/"|sh
没有经过实际测试,如果它打破了,你可以保留两个部分。
编辑:由于丹尼斯不仅指出它分成两部分:-)更正了第二个例子中的拼写错误并删除了第一个
它适用于我使用两个步骤查找:首先删除允许的文件,然后删除它们的空目录!
find -x -E ~/Desktop/test -not \( -type d -regex '.*/(cupcake|livewire)/*.*' -prune \) -print0 | xargs -0 ls -1 -dG
# delete the files first
# Mac OS X 10.4
find -x -E ~/Desktop/test -not \( -type d -regex '.*/(cupcake|livewire)/*.*' -prune \) -type f -exec /bin/rm -fv '{}' \;
# Mac OS X 10.5
find -x -E ~/Desktop/test -not \( -type d -regex '.*/(cupcake|livewire)/*.*' -prune \) -type f -exec /bin/rm -fv '{}' +
# delete empty directories
find -x ~/Desktop/test -type d -empty -delete
像其他人一样,我使用os.walk和os.path.join构建要删除的文件列表,使用fnmatch.fnmatch选择必须包含或排除的文件:
#-------------------------------#
# make list of files to display #
#-------------------------------#
displayList = []
for imageDir in args :
for root,dirs,files in os.walk(imageDir) :
for filename in files :
pathname = os.path.join( root, filename )
if fnmatch.fnmatch( pathname, options.includePattern ) :
displayList.append( pathname )
#----# now filter out excluded patterns #----#
try :
if len(options.excludePattern) > 0 :
for pattern in options.excludePattern :
displayList = [pathname for pathname in displayList if not fnmatch.fnmatch( pathname, pattern ) ]
except ( AttributeError, TypeError ) :
pass
如果fnmatch不够,可以使用re模块测试模式。
在我做任何事情之前,我已经构建了文件列表,但您可以在生成文件时处理这些文件。
如果我的选项类实例没有排除模式,或者它在fnmatch中导致异常,因为它是错误的类型。
此方法的局限性在于它首先包含与模式匹配的文件, 然后排除 。 如果你需要比这更灵活(包括匹配模式a,但不包括模式b,除非模式c ...),那么上面的片段不符合它。 实际上,通过本练习,您将开始了解查找命令语法的原因。 看起来很笨,但事实上它正是这样做的方式。
但是,如果生成列表,则可以根据所需的包含/排除规则对其进行过滤。
生成列表的一个好处是你可以在继续删除之前检查它。 这有点像'--dryrun'选项。 您可以在python解释器中以交互方式执行此操作,打印列表以查看其外观,应用下一个过滤器,查看它是否已删除太多或太少等等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.