26

我有一些文件,比如

love.txt  
loveyou.txt 

在目录中useful;我想将此文件复制到目录/tmp

我使用这个命令:

find ./useful/ -name "love*" | xargs cp /tmp/

但它不起作用,只是说:

cp: target `./useful/loveyou.txt' is not a directory

当我使用这个命令时:

 find ./useful/ -name "love*" | xargs -i cp {} /tmp/

它工作正常,

我想知道为什么第二个有效,以及更多关于-i cp {}.

4

6 回答 6

21

xargs将来自标准输入的单词放在给定命令的参数列表的末尾。因此,第一种形式创建

cp /tmp/ ./useful/love.txt ./useful/loveyou.txt

这不起作用,因为有两个以上的参数,最后一个不是目录。

但是,该-i选项告诉xargs一次处理一个文件,{}用它的名称替换,所以它相当于

cp ./useful/love.txt    /tmp/
cp ./useful/loveyou.txt /tmp/

这显然运作良好。

于 2013-08-07T13:30:13.817 回答
11

使用xargs -i命令时,{}将替换为您找到的每个元素。因此,在您的情况下,对于“loveyou.txt”和“love.txt”,将运行以下命令:

cp ./useful/loveyou.txt /tmp/
cp ./useful/love.txt /tmp/

如果你省略{},你找到的所有元素将自动插入到命令的末尾,因此,你将执行无意义的命令:

cp /tmp/ ./useful/loveyou.txt ./useful/love.txt
于 2013-08-07T13:30:19.677 回答
4

第一个示例将执行此操作:

cp /tmp/ love.txt loveyou.txt

这是无法完成的,因为他们试图将目录/tmp和文件复制love.txt到文件中loveyou.txt

在第二个例子中,-i告诉用参数xargs替换每个实例{},所以它会这样做:

cp love.txt /tmp/
cp loveyou.txt /tmp/
于 2013-08-07T13:30:19.273 回答
4

xargs 将作为流输入的值附加到命令的末尾 - 它不会对每个输入值运行一次命令。如果您希望同一命令运行多次 - 这就是 -i cp {} 语法的用途。

这适用于在末尾接受参数列表的命令(例如 grep) - 不幸的是 cp 不是其中之一 - 它认为您传入的参数是要复制到的目录,这解释了“不是目录”错误.

于 2013-08-07T13:30:20.650 回答
3
find ./useful/ -name "love*" | xargs cp -t /tmp/
于 2015-08-11T19:17:09.797 回答
1

您可能会以这种方式避免 xargs :

find ./useful/ -name "love*" -exec sh -c 'cp "$@" /tmp' sh {} +
于 2013-08-07T15:37:12.523 回答