如何在Linux中使用`find`命令删除非空目录?

10

我有很多临时目录,它们都以__temp__开头,里面充满了无用的文件(例如:__temp__user_uploads)。我想使用一个清理函数来删除这些目录。我的函数尝试运行以下命令:

find . -name __temp__* -exec rm -rf '{}' \;

如果我运行该命令,存在多个__temp__目录(__temp__foo__temp__bar),则输出如下:
find: __temp__foo: unknown option

如果我运行该命令且只有一个__temp__目录(__temp__foo),则会删除它并输出:

find: ./__temp__foo: No such file or directory

为什么命令不起作用,为什么会出现不一致的情况,我该如何修复?

1个回答

27

使用深度优先搜索并引用(或转义)shell元字符*

find . -depth -name '__temp__*' -exec rm -rf '{}' \;

说明

如果不使用 -depth 标志,您的 find 命令将删除匹配的文件名,然后尝试进入 (现在已经取消链接的) 目录。这就是你在单个 __temp__ 目录情况下出现 "No such file or directory" 错误的原因。

如果不对 * 进行引用或转义,shell 将扩展该模式,匹配当前工作目录中的多个 __temp__whatever 文件名。这种扩展会混淆 find,因为它在其参数列表的那个位置预期选项而不是文件名。


6
作为提高效率和紧密性的建议,假设使用GNU工具(因为原帖是在Linux上),我实际上会建议使用find . -maxdepth 1 -type d -name '__temp__*' -print0 | xargs -0 rm -rf。该命令的作用是删除以“__temp__”开头的当前目录中的所有子目录和它们的内容。 - pilcrow
建议使用xargs而不是-exec,+1。 - Ashish Kumar
@AshishKumar - 为什么要在xargs中加上+1?-exec不是find的一个好功能吗?pilcrow,感谢您的解释! - orokusaki
2
@orokusaki:-exec 并不是本质上的坏选择,但它会为每个匹配的文件触发一次操作:rm foo,然后 rm bar,以此类推。xargs 会将许多文件名作为参数传递给其子命令,因此更加高效:rm foo bar ... 除非你有成千上万个文件,否则 xargs 只会调用一个 rm 实例。 - pilcrow
2
@orokusaki:这是正确的,-exec会在找到每个文件时执行一次,然后连续分叉外部命令,“rm”在这种情况下。但是,如果您使用“| xargs”,那么find将定位所有文件,将它们存储在一个数组中,然后整个数组将被传递给由“xargs”调用的“rm”,例如rm -fr foo bar qux spam eggs等。再次为pilcrow的解释点赞。 - Ashish Kumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接