find -exec:在 {} 和 + 之间添加参数

ger*_*rit 8 find arguments

我想使用 find 来定位文件,然后将它们复制到一个目录中,所以我尝试了:

find . -name '*.png' -exec cp {} /tmp/dest +
Run Code Online (Sandbox Code Playgroud)

然而,这失败了

find: missing argument to `-exec'
Run Code Online (Sandbox Code Playgroud)

当我用+a替换;它时,它可以工作,但会单独为每个文件调用 cp 。使用 的+形式时如何添加尾随参数(例如目标目录)-exec

当然,在这种情况下,我可以通过使用来解决明显的限制cp -t(例如在 Stack Overflow 上的这篇文章中指出,但该解决方案特定于cp。相反,我可能会使用 rsync、scp 或其他一些工具。是否有在{}+in之间添加参数的一般方法find -exec

Kus*_*nda 12

不,如果你使用的-exec ... {} +,有可能是之间没有任何东西{}+离开空白。没有办法解决这个问题。

从POSIX标准规格find命令

-exec utility_name [argument ...] ;
-exec utility_name [argument ...] {} +

主要表达式的结尾应以 a<semicolon>或 a标点<plus-sign>。只有<plus-sign>紧跟在仅包含两个字符的参数之后的 a 才{}应标点主表达式的结尾。的其他用途<plus-sign>不应被视为特殊用途。

一个更通用的解决方案可能是

find ... -exec sh -c 'cp "$@" /tmp/dest' sh {} +
Run Code Online (Sandbox Code Playgroud)

在这里,使用sh -c来自find. 在内联脚本中,"$@"将是传递的参数列表(单独引用),这允许我们将它们放置在cp命令行中。

这允许我们使用非 GNU cp(例如,在 macOS 或其他 BSD 系统上,没有-t选项)或任何其他实用程序,其中人们可能希望将其他参数添加到来自find.

有关的:


没有人要求这个,但无论如何......

使用变量中的目标目录,destdir

destdir=/tmp/dest

find ... -exec sh -c 'destdir=$1; shift; cp "$@" "$destdir"' sh "$destdir" {} +
Run Code Online (Sandbox Code Playgroud)

请注意,destdir在shell调用的find是一个独立的变量将destdirsh -c脚本中。

或者,使用bash

destdir=/tmp/dest

find ... -exec bash -c 'cp "${@:2}" "$1"' bash "$destdir" {} +
Run Code Online (Sandbox Code Playgroud)

这是“切片”"$@"列表,以便为cp命令行适当地重新排列它,而不$1将目标目录路径名提取到单独的变量中。

  • @gerrit 第二个`sh` 是内嵌脚本中`$0` 中的内容。它是在`sh -c` shell 产生的任何错误消息中使用的任意字符串。没有它,第一个参数会以 `$0` 结尾,并且不会被 `cp` 复制(因为 `$0` 不是 `"$@"` 的一部分)。 (3认同)
  • @nezabudka One 还可以注意到,`sh` 可能是最相关的字符串,因为它用于该 shell 产生的错误消息中,就像您执行 shell 脚本一样。 (2认同)
  • @gerrit [`sh -c 'some shell code' sh` 中的第二个 sh 是什么?](https://superuser.com/q/1526229/432690) (2认同)