find 的“-exec rm {} \;” 与“-删除”

Oni*_*ion 358 find

我试图了解这两个命令之间的区别:

sudo find / -name .DS_Store -delete
Run Code Online (Sandbox Code Playgroud)

sudo find / -name ".DS_Store" -exec rm {} \;
Run Code Online (Sandbox Code Playgroud)

我注意到该-exec ... {}方法是首选。为什么?哪个更安全/更快/更好?我在我的Macbook上都使用过,一切似乎都运行良好。

Cel*_*ada 351

-delete将有更好的表现,因为它没有产卵为每一个匹配的文件外部的过程,但请务必使用它使用它之后-name,否则将删除指定的整个文件树。

例如,

find . -name .DS_Store -type d -delete
Run Code Online (Sandbox Code Playgroud)

您可能会-exec rm {} +经常看到推荐,因为-delete并非所有版本的find. 我现在无法检查,但我很确定我没有使用find它。

这两种方法都应该是“安全的”。

避免为每个匹配的文件生成外部进程的开销的常用方法是:

find / -name .DS_Store -print0 | xargs -0 rm
Run Code Online (Sandbox Code Playgroud)

(但请注意,这里也存在可移植性问题:并非所有版本的 find 都有-print0!)

  • 在最近的 `find` 中,您可以使用 `-exec rm {} +` 使​​用单个 `rm` 命令删除所有匹配的文件。 (18认同)
  • 我知道了。我也读过在 `-name` 删除指定的文件树之前使用 `-delete` 开关,所以我想我必须小心。 (6认同)
  • `.DS_Store` 根本不包含任何特殊字符,所以引号是不必要的,在这种情况下没有任何改变。 (3认同)
  • @MarcoMarsala `xargs` 将有限大小的参数列表问题分解为多个命令调用,从而透明地处理它。 (3认同)
  • 基本上只有空格(空格、制表符,也许其他)是唯一导致未加引号的字符串被解释为两个单独的命令行参数的因素,但这并不是您在决定是否引用时需要遗憾的全部。您必须担心 *所有* shell 元字符,例如 `;` 或 `|` 或 `>` 或 `<` 和 `\` 以及许多其他对 shell 具有特殊含义的字符(除非引用)。 (2认同)
  • @Valerio“find”命令后的第一个参数是起始目录,通常是“.”。对于[当前目录],而“/”将从完整运行的系统根目录开始(除非在 chroot 或其他类似目录中运行)。 (2认同)

jll*_*gre 44

假设.DS_Store代表文件而不是目录,最便携但最快速的方法是:

sudo find / -name .DS_Store -exec rm {} +
Run Code Online (Sandbox Code Playgroud)

唯一的风险是sudo不可用,但现在已经相当低了。

-delete用于要求 GNU find的选项在许多其他find实现中仍然是非标准的,因此并不总是可用。

命令终止+而不是通过不为文件系统上的每个存在运行命令来\;高度优化exec子句。rm.DS_Store

  • `-delete` 来自 1996 年的 FreeBSD,直到 2004 年才添加到 GNU find 中,`-exec cmd {} +` 来自 80 年代的 SysV,1992 年由 POSIX 标准化,2005 年添加到 GNU find 中。 (11认同)

小智 23

对于像 macbook 这样的机器,您不会发现这两个命令之间的性能差异很大。但是,如果您查看-exec版本,您会发现一个细微的区别:

sudo find / -iname ".file-to-delete"  -exec rm {} \;
Run Code Online (Sandbox Code Playgroud)

这意味着您将找到所有名称为 的文件.file-to-delete。但是,此搜索可能会返回一些不需要的误报。和sudo你一起做事时要小心一点。使用的好处-exec rm {}是你可以rm像这样传递参数:

sudo find / -iname "*~"  -exec rm -i {} \;
Run Code Online (Sandbox Code Playgroud)

在这个例子中,我想删除那些制作的备份文件emacs。然而,波浪号可能在一些我不知道的晦涩文件中,并且可能很重要。另外我想确认删除。所以我把选项-i放在rm命令上。这会给我一个交互式删除。

您还可以优化rm删除目录和文件的用法:

find /usr/local/share/ -iname "useless" -exec rm -r {} \;
Run Code Online (Sandbox Code Playgroud)

简而言之, 可以-exec让您更好地控制删除找到的项目的实际命令。优点是您可以使用一种工具来查找文件,使用另一种工具来删除它们。并非每个版本的 find 实用程序都有该-delete选项。因此最好使用每种工具来完成其正确的工作。这就是 Unix 哲学——一个工具,一份工作,一起使用它们来做你需要做的事情。

  • 另请参阅`-ok rm {} \;` 代替`-exec rm {} \;` 进行交互确认。 (7认同)

miv*_*ivk 5

除了现有答案之外,请注意,-delete如果目录不为空,则不会删除目录。-exec rm -r所以在这些情况下你需要。

\n

例如,这不起作用:

\n
$ find . -type d -name ".TemporaryItems" -delete\nfind: cannot delete \xe2\x80\x98./.TemporaryItems\xe2\x80\x99: Directory not empty\n
Run Code Online (Sandbox Code Playgroud)\n

所以你需要这个:

\n
find . -type d -name ".TemporaryItems" -exec rm -rv "{}" +\n
Run Code Online (Sandbox Code Playgroud)\n

该示例将-v(--verbose) 选项添加到 rm。

\n