LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   how to use cp find and grep together to copy a list of files using find with grep (https://www.linuxquestions.org/questions/linux-newbie-8/how-to-use-cp-find-and-grep-together-to-copy-a-list-of-files-using-find-with-grep-4175467956/)

babhijit 07-01-2013 01:24 AM

how to use cp find and grep together to copy a list of files using find with grep
 
I am getting a list of files using the following command:

find . type -f | xargs grep -l 19201020320

now I want to modify the above command so that the listing produced by the above command can be copied to a folder (say /tmp).

Tried the following but did not work!

find . type -f | xargs grep -l 19201020320 | xargs cp /tmp

Got the error message:
cp: copying multiple files, but last argument `./XYZ.20130701.060000' is not a directory
Try `cp --help' for more information.

Madhu Desai 07-01-2013 01:59 AM

Code:

find . -type f -name "*19201020320*" -exec cp '{}' /tmp \;

babhijit 07-01-2013 02:28 AM

My criteria is searching in files for a given string .. in this case "19201020320". Shouldn't -name in find search for files having file names "*19201020320*"? :)

Madhu Desai 07-01-2013 03:33 AM

Try this:
Code:

#!/bin/bash
for file in $(find . -type f -exec grep -l "19201020320" '{}' +)
do
  cp $file /tmp
done


asimba 07-01-2013 03:41 AM

Try following anf see if it works

Code:

grep -l 19201020320 ./* |  xargs -I {} cp {} ./tmp/

TobiSGD 07-01-2013 04:26 AM

Quote:

Originally Posted by babhijit (Post 4981524)
find . type -f | xargs grep -l 19201020320 | xargs cp /tmp

Just to explain why this won't work: xargs will append the input it gets from the pipe to the end of the command, so that you will in your case have the destination directory before the source files, while cp expects it to be the other way around. For cases like these cp has the -t option, which will allow you to specifically name the destination directory. If you change your command to
Code:

find . type -f | xargs grep -l 19201020320 | xargs cp -t /tmp
it should work.

asimba 07-01-2013 04:27 AM

I am unsure as why find command is being used - Is using grep directly inefficient ?

babhijit 07-01-2013 04:29 AM

Yeap. That's what I was looking for :)

babhijit 07-01-2013 04:35 AM

I am a newbie trying to feel around linux .. its more of an issue of getting through things rather than performance :P

David the H. 07-03-2013 11:43 AM

Quote:

Originally Posted by mddesai (Post 4981569)
Try this:
Code:

#!/bin/bash
for file in $(find . -type f -exec grep -l "19201020320" '{}' +)
do
  cp $file /tmp
done


No, please Don't Read Lines With For! The output of commands should always be processed with a while+read loop, or some other similar technique that allows you to safely delimit the input with null separators.

Always remember to quote your variables too, for similar reasons.

Code:

#!/bin/bash
while IFS='' read -d '' -r fname; do
    cp "$fname" /tmp
done < <( find . -type f -exec grep -lZ "19201020320" '{}' + )

In this particular case, since it's grep doing the actual printing, we need to use its -Z option for null separators, rather than the usual -print0 of find.

Of course we can also use xargs instead of the loop, since it can handle null separated input too.

Code:

find . -type f -exec grep -lZ '19201020320' '{}' + | xargs -0 cp -t /tmp
And actually, find can probably be eliminated as well, since grep can do recursive searching all by itself.

Code:

grep -lZR '19201020320' . | xargs -0 cp -t /tmp
You can also add --include and --exclude options for more exact file filtering if needed. See the man/info pages.

Finally, notice how I used the -t option in cp, to invert the order of the arguments and make the command simpler. I believe this is only available in gnu cp, however.


PS: Please use ***[code][/code]*** tags around your code and data, to preserve the original formatting and to improve readability. Do not use quote tags, bolding, colors, "start/end" lines, or other creative techniques. Thanks.

Madhu Desai 07-03-2013 12:25 PM

@David the H.

Thanks for showing my mistakes. your suggestions were truly insightful. I really appreciate that. :hattip:


All times are GMT -5. The time now is 10:26 PM.