递归删除除几个子目录之外的所有子目录

递归删除除几个子目录之外的所有子目录

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)将匹配所有未调用的abcdef(我假设您已经删除了文件,否则使用稍微不同的模式您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标志实际上可以删除文件和目录。

相关内容