'find -empty -delete' 删除非空目录

'find -empty -delete' 删除非空目录

如果我创建以下目录结构:

mkdir -p dir1/dir2/dir3/dir4

然后我运行find dir1,它返回:

dir1
dir1/dir2
dir1/dir2/dir3
dir1/dir2/dir3/dir4

如果我运行find dir1 -empty,它仅返回:

dir1/dir2/dir3/dir4

显示只有 dir4 是空的。

但是,如果我运行find dir1 -empty -delete,所有四个目录都会立即删除。

我希望只删除 dir4,那么下次运行该命令时,只会删除 dir3,依此类推。为什么会发生这种情况,如何使用 只删除 dir4 find

答案1

因为-delete暗示-depth,或深度优先迭代,所以find首先查看dir1/dir2/dir3/dir4,注意到它是空的,将其删除,然后查看dir1/dir2/dir3,注意到它(现在)是空的并删除它......

GNU 手册页说:

-depth
在处理目录本身之前处理每个目录的内容。动作-delete还暗示着-depth

这可能是他们认为能够删除一些文件,然后可能删除包含这些文件的目录(如果同时清空的话)(-delete不会递归地删除整个子树),而不是必须重复,这可能更有用命令find,直到所有匹配的文件和目录都消失。或者从另一个角度来看,仅删除树的叶子(正如我们在这里想要的那样)并不是幂等的:意外地再次运行该命令会从目录树中删除另一层。

在任何情况下,您都可以find运行rmdir以保持默认模式,并添加-prune以防止它尝试下降到现已删除的目录。我们-print也在这里添加调试功能,这样我们就可以看到它删除了什么:

$ mkdir -p dir1/dir2/dir3/dir4
$ find -type d -empty -exec rmdir {} \; -prune -print
./dir1/dir2/dir3/dir4

这就是剩下的:

$ find
.
./dir1
./dir1/dir2
./dir1/dir2/dir3

(在这里,如果rmdir失败,该-exec操作将被评估为假,并且-prune-print操作将不会运行。因此到 stdout 的打印输出应该只包含实际删除的内容。这与 不同-exec rmdir {} +。)

当然,假设您只想删除此处的空目录,如果您还想删除空文件,您可以先使用

find -type f -empty -delete

rm或者构建需要文件和rmdir目录的糟糕组合:

find -empty \( -type f -exec rm {} \; -o -type d -exec rmdir {} \; -prune \) -print

rm -rf显然也可行,但风险更大。)

相关内容