I have some file like
love.txt
loveyou.txt
in directory useful
; I want to copy this file to directory /tmp
.
I use this command:
find ./useful/ -name "love*" | xargs cp /tmp/
but is doesn't work, just says:
cp: target `./useful/loveyou.txt' is not a directory
when I use this command:
find ./useful/ -name "love*" | xargs -i cp {} /tmp/
it works fine,
I want to know why the second works, and more about the usage of -i cp {}
.
xargs
puts the words coming from the standard input to the end of the argument list of the given command. The first form therefore creates
cp /tmp/ ./useful/love.txt ./useful/loveyou.txt
Which does not work, because there are more than 2 arguments and the last one is not a directory.
The -i
option tells xargs
to process one file at a time, though, replacing {}
with its name, so it is equivalent to
cp ./useful/love.txt /tmp/
cp ./useful/loveyou.txt /tmp/
Which clearly works well.
When using the xargs -i
command, {}
is substituted with each element you find. So, in your case, for both "loveyou.txt" and "love.txt", the following command will be run:
cp ./useful/loveyou.txt /tmp/
cp ./useful/love.txt /tmp/
if you omit the {}
, all the elements you find will automatically be inserted at the end of the command, so, you will execute the nonsensical command:
cp /tmp/ ./useful/loveyou.txt ./useful/love.txt
The first example will do this:
cp /tmp/ love.txt loveyou.txt
Which can't be done, since they attempt to copy the directory /tmp
and the file love.txt
to the file loveyou.txt
.
In the second example, -i
tells xargs
to replace every instance of {}
with the argument, so it will do:
cp love.txt /tmp/
cp loveyou.txt /tmp/
xargs appends the values fed in as a stream to the end of the command - it does not run the command once per input value. If you want the same command run multiple times - that is what the -i cp {} syntax is for.
This works well for commands which accept a list of arguments at the end (eg grep) - unfortunately cp is not one of those - it considers the arguments you pass in as directories to copy to, which explains the 'is not a directory' error.
find ./useful/ -name "love*" | xargs cp -t /tmp/
你可以这样避免xargs:
find ./useful/ -name "love*" -exec sh -c 'cp "$@" /tmp' sh {} +
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.