为什么在更短、更容易输入和阅读的文章似乎同样有效的情况下find
总是使用上面的文章?据我所知?-exec rm {} \;
-delete
我意识到有些情况下rm
有一些选择例如-r -f
可能会做更多的技巧,但是整个网络上的教程中有大量简单的例子-exec rm {} \;
,但几乎没有使用的例子-delete
。
我错过了什么?这有什么原因吗?
答案1
tl;dr:-delete
POSIX 不需要,-exec
是的。
事实
POSIX 1003.1 手册页find
指定-exec
但没有-delete
。
这种方式几乎可以在任何地方使用。如果没有,-exec
我会惊讶地发现find
有。相反的情况是完全可能的。特别是轻量级系统往往只提供基本的命令行选项。-delete
-exec
busybox
例如,我的一个路由器上有一个 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 {} +
rm
rm
那么为什么不被-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 '{}' \'
比几乎所有情况都快。