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

maa*_*nus 186 directory find rm

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

find . -type d -exec rmdir {} 2>/dev/null \;
Run Code Online (Sandbox Code Playgroud)

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

Chr*_*uet 281

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

find . -type d -empty -delete
Run Code Online (Sandbox Code Playgroud)
  • -type d 限制到目录
  • -empty 限制为空的
  • -delete 删除每个目录

树是从叶子中走出来的,不需要指定,-depth因为它是由 暗示的-delete

  • 我会在这里添加 ```-mindepth 1```,以防止删除起始目录本身,如果它是空的。 (16认同)
  • `-delete` 已经暗示了 `-depth`,因此您无需手动指定。 (2认同)
  • 谢谢,我没有意识到这一点。答案已更新。 (2认同)
  • 很好,但在我的旧 SunOS 主机上不起作用... (2认同)
  • `!` 对 shell 有特殊的意义。你需要逃避它。类似于:`\! -name 'Completed'` 就在 `-delete` 应该工作之前。或者您只需在此目录中放置一个标记文件。 (2认同)

Gil*_*il' 56

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

find . -depth -type d -exec rmdir {} \; 2>/dev/null
Run Code Online (Sandbox Code Playgroud)

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

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

find . -depth -type d -empty -exec rmdir {} \;
Run Code Online (Sandbox Code Playgroud)

另一种加快速度的方法是对rmdir调用进行分组。两者都可能比原始版本快得多,尤其是在 Cygwin 下。我不希望这两者之间有太大区别。

find . -depth -type d -print0 | xargs -0 rmdir 2>/dev/null
find . -depth -type d -exec rmdir {} + 2>/dev/null
Run Code Online (Sandbox Code Playgroud)

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

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

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

或者,使用 zsh。在预选赛中的glob F匹配非空目录,所以/^F匹配空目录。只包含空目录的目录不能那么容易匹配。

while rmdir **/*(/N^F); do :; done
Run Code Online (Sandbox Code Playgroud)

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

  • @maartinus — 其他一些小优化:添加 `-empty` 应该适用于这个(虽然我不确定它会获得多少)。非常非常简单,因为您可能不想删除`.`,请使用`-mindepth 1`。 (3认同)
  • 我意识到我们可以完全删除 `rmdir` 命令调用,至少在 GNU find 中,使用这个命令:`find 。-depth -type d -empty -delete` (2认同)

mat*_*tdm 6

如果你只是-p在你的上加上一个rmdir,那将在一次通过中起作用。它不会很漂亮或最佳,但它应该得到一切。这告诉 rmdir 删除您要删除的目录的任何非空父目录。

您可以通过添加-empty要查找的测试来节省一点,因此它不会打扰非空目录。


sch*_*ily 6

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

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

不幸的是,此处给出的其他答案都取决于并非所有系统上都存在的供应商特定增强功能。

  • 对于每个无法删除的目录,此答案都会引发错误,这可能不太理想。 (4认同)