如何删除子树中的所有空目录?我使用了类似的东西,但我需要多次运行才能删除仅包含空目录的目录。而且,它非常慢,尤其是在cygwin下。

评论

另请参阅emacs.stackexchange.com/q/12190/2264以获取emacs解决方案。

#1 楼

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

find . -type d -empty -delete





-type d限于目录

-empty限制为空的

-delete删除每个目录

树从树叶上走了,而无需指定-depth,因为-delete隐含了它。

评论


-delete已经暗示-depth,因此您无需手动指定。

–贾马达格尼
2014年9月19日下午2:31

谢谢,我没意识到。答案已更新。

–克里斯托弗·德雷维特·德洛格(Christophe Drevet-Droguet)
2014-09-19 15:57

我将在此处添加-mindepth 1,以防止删除启动目录本身(如果该目录为空)。

– Greg Dubicki
16年8月20日在12:49

很好,但是在我的旧SunOS主机上不起作用...

– dokaspar
17年8月8日在10:05

!对外壳有特殊的含义。您需要逃脱它。就像是: \! -name应该在-delete应该起作用之前“已完成”。或者,您只需将标记文件放在此目录中。

–克里斯托弗·德雷维特·德洛格(Christophe Drevet-Droguet)
18年4月2日在8:34

#2 楼



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


(请注意,重定向整体上适用于find命令,而不仅适用于rmdir。仅重定向rmdir会导致严重的减速,因为您需要调用中间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收到空命令行时,该目录终止。)

评论


而已。耗时0.9秒,而不是90秒。

– maaartinus
2011年3月1日22:14



@maaartinus:我很好奇:您是否有类似的数据集可以在没有-p的情况下尝试?我不会想到这会有所作为。

–吉尔斯'所以-不再是邪恶的'
2011年3月1日22:15

@maartinus —其他一些小的优化:添加-empty应该可以与此(尽管我不确定它会获得多少)一起使用。而且非常非常琐碎,因为您可能不想删除。,所以请使用-mindepth 1。

–mattdm
2011年3月1日22:19

并不是所有的时间都花在了搬迁上,而是花在了整个过程上。我忽略了-depth参数,这使rmdir -p无效。我已经更改了评论。 90年代是我最初的尝试;这里没有什么奇怪的。

– maaartinus
2011年3月1日22:20在

我意识到,至少可以使用GNU find,使用以下命令可以完全删除rmdir命令调用:find。深度-类型d-空-删除

–克里斯托弗·德雷维特·德洛格(Christophe Drevet-Droguet)
2014年1月2日14:26



#3 楼

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

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

#4 楼

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

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

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

评论


对于每个无法删除的目录,此答案都会引发一个错误,该错误可能不那么理想。

–威廉·范·凯奇(Willem van Ketwich)
17年4月13日在0:04

#5 楼

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

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


#6 楼

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

它的工作方式是:


递归列出所有目录及其深度
按深度的降序排列
仅过滤出目录路径
一一运行在列表上的rmdir


#7 楼

rm -r */命令对我来说很容易工作。 rm应该要求-f强制删除包含文件的目录。 rm -r应该只删除空目录。我很乐意为什么这可能是错误的。这也应该留下文件,因为*/仅查看文件夹。

评论


我强烈建议先彻底测试它,因为rm主要是为了删除文件。虽然* /只匹配目录,但我不知道它在更深层次上的作用。我也可以想象它仅在某些系统上有效。

– maaartinus
18年6月22日在19:30