查找:“-exec rm {} \;” 与“-delete” - 为什么前者被广泛推荐?

查找:“-exec rm {} \;” 与“-delete” - 为什么前者被广泛推荐?

为什么在更短、更容易输入和阅读的文章似乎同样有效的情况下find总是使用上面的文章?据我所知?-exec rm {} \;-delete

我意识到有些情况下rm 有一些选择例如-r -f可能会做更多的技巧,但是整个网络上的教程中有大量简单的例子-exec rm {} \;,但几乎没有使用的例子-delete

我错过了什么?这有什么原因吗?

答案1

tl;dr:-deletePOSIX 不需要,-exec是的。


事实

POSIX 1003.1 手册页find指定-exec但没有-delete

这种方式几乎可以在任何地方使用。如果没有,-exec我会惊讶地发现find有。相反的情况是完全可能的。特别是轻量级系统往往只提供基本的命令行选项。-delete-execbusybox

例如,我的一个路由器上有一个 OpenWRT,它find可以理解-exec,但它不能理解-delete

当你有的时候,没有-delete也没什么大不了的-exec rm …。另一方面,一般来说-delete不能替换。首先-exec允许省略是一个明智的设计。-delete


个人经历、观察和观点

以上应该是被广泛推荐的主要原因-exec rm {} \;。次要原因可能是滚雪球效应。用户阅读文章和示例,熟悉-exec并发布自己的命令(例如这里超级用户)。他们中的一些人甚至可能不知道-delete存在。

我很少看到(或给出)类似“你可以使用-delete”的评论。而他们的回答是“谢谢,我不知道”。我不记得有任何回答是“我知道,但这不是 POSIX”。


说了这么多,我倾向于-delete-exec rm {} \;出现时提及。原因是-delete它不会产生新进程,而会为每个匹配的文件-exec rm {} \;调用一个单独的进程。如果你不能使用,那么你的下一个想法应该是可以用一个进程删除多个文件(如果需要,它仍然会调用多次)。rm-delete-exec rm {} +rmrm

那么为什么不被-exec … +广泛推荐呢?可能是因为它的局限性。我可以想象一个没有经验的用户会想“这适用于rm,让我用它mv!“然后-exec mv {} foo/ +不起作用,因为{}需要放在最后,就在 之前+。用户感到沮丧并跑回妈妈Windows。


我认为,在超级用户这里推荐-delete通常是安全的。大多数问题都指定了“大型”操作系统,find那里的命令选项丰富。即使有用户能力find有限,我也可能会得到反馈。他或她说解决方案对他们不起作用,我建议-exec rm …解释问题等等。

单独的推荐文章-delete不会得到这样的反馈。如果遇到任何问题,用户只需转到 Google 返回的下一个链接即可。

答案2

不同之处在于灵活性。如果使用 -exec,则可以为每个选定的文件执行一个命令。如果使用 -exec,则可以灵活地应用其他查找选项。使用 -delete 时,使用 -prune 会受到限制。此外,-delete 的放置位置会影响结果。请参阅下面的文档片段:

-delete
    Delete  files;  true  if removal succeeded.  If the removal failed, 
    an error message is issued.  If -delete fails, find’s exit status will be
        nonzero (when it eventually exits).  Use of -delete automatically turns on 
    the ‘-depth’ option.

    Warnings: Don’t forget that the find command line is evaluated as an 
    expression, so putting -delete first will make find try to delete every-
    thing  below  the  starting  points  you  specified.   When testing a find 
    command line that you later intend to use with -delete, you should
    explicitly specify -depth in order to avoid later surprises.  
    Because -delete implies -depth, you cannot  usefully  use  -prune  and  -delete
    together.

-exec command ;
    Execute  command;  true  if 0 status is returned.  All following arguments 
    to find are taken to be arguments to the command until an argument
    consisting of ‘;’ is encountered.  The string ‘{}’ is replaced by the 
    current file name being processed everywhere it occurs in the arguments
    to  the  command, not just in arguments where it is alone, as in 
    some versions of find.  Both of these constructions might need to be escaped
    (with a ‘\’) or quoted to protect them from expansion by the shell.  
    See the EXAMPLES section for examples of the use of  the  -exec  option.
    The specified command is run once for each matched file.  The 
    command is executed in the starting directory.   There are unavoidable security
    problems surrounding use of the -exec action; you should use the -execdir 
    option instead.

-exec command {} +
    This variant of the -exec action runs the specified command on the 
    selected files, but the command line is built by appending  each  selected
    file name at the end; the total number of invocations of the command 
    will be much less than the number of matched files.  The command line is
    built in much the same way that xargs builds its command lines.  
    Only one instance of ‘{}’ is allowed within the  command.   The  command  is
    executed in the starting directory

答案3

较旧的“广泛推荐”形式,在没有 的系统上仍然是首选-delete,是(根据需要替换省略号):

find ... -print0 ... | xargs -0 /bin/rm ...

这会将进程限制为两个,而不是让其-exec产生可能数千个进程,同时仍能正确处理带有特殊字符的文件名(而使用 -print0 并从 xargs 中省略 -0 会导致文件名被错误拆分)。

find它比使用了多一个进程,-delete并且有一些进程间通信开销,但是,与-delete 极大地find ... -exec /bin/rm '{}' \'比几乎所有情况都快。

相关内容