main_directory 包含 0001 0102 0203 ... 子目录。子目录包含很多目录。我需要删除除名称为“abc”、“bcd”和“123”的几个子目录之外的所有子目录。
如何使用命令进行此删除处理?
答案1
虽然快捷但很粗糙,但非常有效:
shopt extglob # possibly already there
shopt globstar # not often the default
rmdir ./**/!(abc|def) # rinse and repeat
慢动作:
extglob
启用 bash 扩展模式(包括类似于!(abc|def)
(任何但abc
不是def
)globstar
匹配**
任意级别的目录- 因此
./**/!(abc|def)
将匹配所有未调用的abc
或def
(我假设您已经删除了文件,否则使用稍微不同的模式您rm
也可以删除文件[*]) - 由于目录是自上而下列出的,因此
rmdir
顶层的目录将在较低层的目录被删除之前出现,这就是为什么您可能需要重复该命令几次。
更加经典find
您还可以使用find
(与-depth
首先处理子目录):
find . -depth -type d \( \! -name 'abc' -a \! -name 'def' \) -exec rmdir {} \;
但是正如您所看到的,如果您有多个需要忽略的目录,命令将会相当冗长。
[*]rm ./**/!(abc|def)/*.txt
例如
答案2
我认为你最好的选择是使用find
我相信这个命令会实现你想要的效果。
find /path/to/dir/ -not -path "*/abc*" -not -path "*/bcd*" -not -path "*/123*" -type f -delete
但我建议不要使用-delete
或第type f -delete
一个,这样你就能知道删除了什么。或者甚至在测试目录集上运行它,以确保它在对你的重要文件运行之前按照你的想法运行。
有关此方法和其他方法的详细信息,find
请参阅以下问题
https://unix.stackexchange.com/questions/87258/delete-all-files-except-in-a-certain-subdirectory-with-find
编辑:
为了消除关于使用-type f
而不是 的一些困惑-type d
,如果你尝试一下,你会发现它确实做到了 OP 所要求的。该-type d
标志实际上导致文件和目录的列出顺序不同。因此,delete
在目录中的文件被删除之前尝试删除目录(这是不允许的)。因此,要使用该-type d
标志,必须反转列出的文件的顺序,这是可能的,但也似乎是一个不必要的步骤,因为该type -f
标志实际上可以删除文件和目录。