查找-exec rm vs -delete


260

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

sudo find / -name .DS_Store -delete

sudo find / -name ".DS_Store"  -exec rm {} \;

我注意到该exec方法是首选。为什么?哪一个更安全/更快/更好?我已经在Macbook上使用过,并且一切似乎都正常运行。

Answers:


245

-delete 会更好地执行,因为它不必为每个匹配的文件生成外部进程。

您可能会-exec rm {} \;经常看到推荐的内容,因为-delete并非所有版本的都存在find。我现在无法检查,但是我敢肯定我已经find没有了。

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

编辑来自@doitmyway的每个注释:确保名称匹配,然后删除,而不是相反(删除,然后匹配)。否则,无论是否匹配,每个文件都将被删除。即,请勿这样做:find / -delete -name .DS_Store

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

find / -name .DS_Store -print0 | xargs -0 rm

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


2
我懂了。我也读过-delete-name删除指定的文件树之前使用开关,所以我想我必须要小心。
洋葱

8
最近,find您可以使用-exec rm {} +单个rm命令删除所有匹配的文件。
jimmij 2014年

3
.DS_Store根本不包含任何特殊字符,因此引号是不必要的,在这种情况下不做任何更改。
Celada 2014年

1
基本上,只有空白(空格,制表符,可能还有其他空格)是导致未加引号的字符串被解释为两个单独的命令行参数的唯一原因,但这并不是您在决定是否引用时所要担心的全部。您必须担心所有外壳元字符(如;or |>or <和``以及许多其他对外壳具有特殊含义的字符,除非引用)
Celada

1
@MarcoMarsala xargs通过将其分解为命令的多个调用来透明地处理有限大小的参数列表问题。
Celada

27

假设.DS_Store代表文件而不是目录,则最可移植但仍最快的方法是:

sudo find / -name .DS_Store -exec rm {} +

唯一的风险是sudo不可用,但如今它的风险仍然很低。

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

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


16

对于诸如Macbook之类的机器,这两个命令之间的性能差异不会太大。但是,如果查看-exec版本,则可以看到细微的差别:

sudo find / -iname ".file-to-delete"  -exec rm {} \;

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

sudo find / -iname "*~"  -exec rm -i {} \;

在此示例中,我想删除emacs创建的那些备份文件。但是,代字号可能存在​​于一些我不知道的模糊文件中,这可能很重要。另外,我要确认删除。因此,我将选项“ -i”放在rm命令上。这将给我一个交互式删除。

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

find /usr/local/share/ -iname "useless" -exec rm -r {} \;

简而言之,-exec使您对删除已找到项目的实际命令有更多控制。好处是您可以使用一种工具查找文件,而使用另一种工具删除文件。同样,并不是每个版本的find实用程序都具有-delete选项。因此最好使用每种工具来完成其适当的工作。这是Unix的理念-一种工具,一项工作,将它们一起使用以完成您需要做的事情。


3
另请参见 -ok rm {} \;代替以-exec rm {} \;进行交互式确认。
库萨兰达
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.