it-swarm.cn

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

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

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

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

159
maaartinus

结合GNU find)选项和谓词,此命令可以完成此任务:

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

树从叶子上走下来,无需指定-depth,因为它由-delete

237

列出目录,然后按深度嵌套。

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

(请注意,重定向整体上适用于find命令,而不仅适用于rmdir。仅针对rmdir重定向将导致速度显着下降,因为您需要调用中间Shell )

您可以通过传递-empty谓词来查找,从而避免在非空目录上运行rmdir。 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收到空命令行时终止。)

53

如果您只是在rmdir上加上-p,则只需一遍。它不会是漂亮的或最佳的,但是它应该可以得到所有。这告诉rmdir删除要删除的目录的所有非空父目录。

您可以添加-empty测试来节省一点时间,因此它不会打扰非空目录。

6
mattdm

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

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

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

3
schily

我将这些别名用于常用的find命令,尤其是当我使用dupegur清理磁盘空间时,删除重复项会导致出现很多空目录。

.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 {} +'
0
raychi

find . -type d -printf "%d %p\n" |\ sort -nr |\ Perl -pe 's/^\d+\s//;' |\ while read dir; do \ (rmdir "$dir" > /dev/null 2>&1); \ done

运作方式如下:

  1. 递归列出所有目录及其深度
  2. 按其深度的降序排序
  3. 仅过滤目录路径
  4. 在清单上一一运行rmdir
0
Ashish Ranjan