如果我创建以下目录结构:
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
显然也可行,但风险更大。)