如何删除子树中的所有空目录?

如何删除子树中的所有空目录?

如何删除子树中的所有空目录?我用过类似的东西

find . -type d -exec rmdir {} 2>/dev/null \;

但我需要运行多次才能删除仅包含空目录的目录。而且,它相当慢,尤其是在cygwin下。

答案1

结合 GNUfind选项和谓词,此命令应该可以完成这项工作:

find . -type d -empty -delete
  • -type d限制为目录
  • -empty限制为空
  • -delete删除每个目录

树是从叶子开始遍历的,不需要指定,-depth因为它是由 暗示的-delete

答案2

首先列出深度嵌套的目录。

find . -depth -type d -exec rmdir {} \; 2>/dev/null

(请注意,重定向适用于find整个命令,而不仅仅是rmdir。仅重定向 forrmdir会导致速度显着减慢,因为您需要调用中间 shell。)

您可以rmdir通过传递谓词进行查找来避免在非空目录上运行-empty。 GNU find 在即将运行该命令时会测试目录,因此将拾取刚刚清空的目录。

find . -depth -type d -empty -exec rmdir {} \;

另一种加速方法是将调用分组rmdir。两者都可能比原始版本快得多,尤其是在 Cygwin 下。我预计这两者之间不会有太大区别。

find . -depth -type d -print0 | xargs -0 rmdir 2>/dev/null
find . -depth -type d -exec rmdir {} + 2>/dev/null

哪种方法更快取决于您有多少个非空目录。您不能结合-empty使用方法进行分组调用,因为这样一来,仅包含空目录的目录在find查看时就不是空的了。

另一种方法是运行多次传递。这是否更快取决于很多因素,包括整个目录层次结构是否可以在find运行之间保留在磁盘缓存中。

while [ -n "$(find . -depth -type d -empty -print -exec rmdir {} +)" ]; do :; done

或者,使用 zsh。这全局限定符 F匹配非空目录,因此/^F匹配空目录。只包含空目录的目录不能那么容易匹配。

while rmdir **/*(/N^F); do :; done

(当rmdir收到空命令行时,这将终止。)

答案3

find . -depth -type d -exec rmdir {} +

是这个问题最简单且符合标准的答案。

不幸的是,这里给出的其他答案都依赖于供应商特定的增强功能,而这些增强功能并非在所有系统上都存在。

答案4

我将这些别名用于常用find命令,特别是当我使用以下命令清理磁盘空间时杜佩古鲁,其中删除重复项可能会导致出现大量空目录。

里面有评论,.bashrc这样我以后需要调整时就不会忘记它们。

# find empty directories
alias find-empty='find . -type d -empty'

# fine empty/zero sized files
alias find-zero='find . -type f -empty'

# delete all empty directories!
alias find-empty-delete='find-empty -delete'

# delete empty directories when `-delete` option is not available.
# output null character (instead of newline) as separator. used together
# with `xargs -0`, will handle filenames with spaces and special chars.
alias find-empty-delete2='find-empty -print0 | xargs -0 rmdir -p'

# alternative version using `-exec` with `+`, similar to xargs.
# {}: path of current file
# +: {} is replaced with as many pathnames as possible for each invocation.
alias find-empty-delete3='find-empty -exec rmdir -p {} +'

# for removing zero sized files, we can't de-dupe them automatically
# since they are technically all the same, so they are typically left
# beind. this removes them if needed.
alias  find-zero-delete='find-zero -delete'
alias find-zero-delete2='find-zero -print0 | xargs -0 rm'
alias find-zero-delete3='find-zero -exec rm {} +'

相关内容