如何通过命令行删除目录中的所有空文件夹?

假设我有一个名为foo/的目录。这个文件夹包含子目录。我该如何用一个命令删除所有空目录?
5个回答

尝试这个命令:
find . -empty -type d -delete
find 命令用于从指定路径中(在此情况下为当前目录,即 .)搜索符合特定搜索条件的文件/目录。 -empty 选项适用于所有空文件和目录。 -type d 选项适用于指定的 文件 类型;在此情况下,d 表示文件类型为 目录-delete 选项是要执行的操作,适用于搜索到的所有文件。

我认为这是最简单的方法,所以我打算继续并标记为已回答。 - justingrif
嘿,比尔,我试着发布另一个类似的问题,但是它不让我发,说是重复的,所以我希望你能在这里回答我。假设我想要做与上面相同的事情,但是无论目录是否为空,都要删除它们。 - justingrif
4无论目录是否为空,您可以使用以下命令删除目录:rm -rf <directory-name>。这将删除目录及其所有内容,包括文件和子目录。选项-r表示递归删除,而选项-f表示在删除前不提示。然而,如果您想在删除目录/文件之前接收提示信息,请将选项-f替换为选项-i - Bill
如果在所述目录中有一些我想保留的文件怎么办?所以,我想删除/foo/bar/中的所有目录,但保留可能存在的任何文件。 - justingrif
2可以通过使用管道将一个命令(例如find)的stdout输入到另一个命令(例如rm)的stdin来实现这一点,但是要非常小心,因为它可能会删除你不想删除的文件/目录!有关如何执行此操作的更多信息,请参阅每个命令的man页面。为了安全起见,在尝试真实操作之前,始终在临时目录中进行测试。 - Bill
在Mac上不起作用,只能删除空的叶子目录,而不能删除仅包含空目录的目录。 - Joey Baruch
1@joeybaruch 在MacOS上,几乎每个你用Finder.app“访问”的目录中都包含一个名为.DS_Store的隐藏文件,该文件通常存储该目录的排序/查看偏好设置。其他应用程序可能会添加其他隐藏文件(例如Adobe Bridge可能会添加一个名为.BridgeLabelsAndRatings的文件),所以这些目录可能并不是真的空的。无论如何,你可以使用命令find . -name '.DS_Store' -delete来删除.DS_Store文件,然后再尝试使用建议的命令删除空目录。 - gerlos
1使用-depth选项,find命令甚至可以匹配并删除那些只因为其所有(空的)子目录被删除而变为空的目录。尝试一下这个命令:mkdir -p a/b/c/d && find a -depth -type d -empty -print -delete - David Foerster

你可以利用 rmdir 命令拒绝删除非空目录的特性,以及 find -depth 选项从底部向上遍历目录树:
find . -depth -exec rmdir {} \;  

(忽略错误),或者在命令后面加上2>/dev/null来真正忽略它们。 -depth选项用于find命令,从目录树的底部开始查找。 rm -rf将删除目录中的所有文件(以及其子目录等等...)和所有目录以及其中的所有内容。

rmdir *

将删除所有空目录。对于每个非空目录和文件,它都会抛出一个错误,为了防止这些错误混乱您的终端,请使用以下命令:
rmdir * 2> /dev/null

这不适合用于脚本编写,因为它会以非零状态码退出,但它是有效的。 - the_drow
@the_drow 它为什么不适用?顺便说一下,你也可以使用 rmdir * 2>/dev/null || true。(find(1) 的方式对于脚本编写来说更好,但出于其他原因:因为它更好地表达了你想要做的事情。) - Alois Mahdal
我经常在$HOME这样做。带着邪恶的笑容。 - Alois Mahdal
因为如果其中一些目录不为空,它将报告失败。 - the_drow
这个方法比find方法快吗?有人比较过这两种方法吗? - xeruf

find . -type d -empty -delete -maxdepth 1

如果你只想删除foo/的直接子目录。

Python 方法

$ tree                                                                                                                                                                                  
.
├── empty_dir1
├── empty_dir2
├── subdir1
│   ├── file1.abc
│   └── file2.abc
└── subdir2
    ├── file1.abc
    └── file2.abc

4 directories, 4 files
$ python -c 'import os;empty=[r for r,s,f in os.walk(".") if not f and not s and r != "." ];map(lambda x: os.rmdir(x),empty)'
$ tree
.
├── subdir1
│   ├── file1.abc
│   └── file2.abc
└── subdir2
    ├── file1.abc
    └── file2.abc

这是如何工作的:
我们使用`os.walk()`函数递归地遍历目录树。 每次迭代时,`r`设置为我们正在访问的当前文件夹, `s` 包含在 `r` 中的目录列表,而 `f` 将包含该文件夹中的文件列表。 当然,如果 `f` 和 `s` 为空,则知道 `r` 为空。
第一个列表推导式允许我们基于上述评估创建所有空目录的`empty`列表。
第二个函数`map()`用于对`empty`列表中的每个项目执行`os.rmdir()`。 列表理解也可以用作替代方法。
作为脚本,它将如下所示:
#!/usr/bin/env python
import os
empty=[]
for r,s,f in os.walk("."):
    if not f and not s and r != ".":
        empty.append(r)

for i in empty:
    os.rmdir(i)

对于简单的问题来说,这太复杂了 :( - nurulhudamustaqim
视角而定。对于许多习惯使用Python的Linux用户来说,这实际上是非常适度的 :) 除此之外,它还具有多样性。现代系统管理不仅限于bash或/bin/sh,而且Python实际上比这两者更优雅。 - Sergiy Kolodyazhnyy