2

I am trying to find files that contain a certain string in a current directory and make a copy of all of these files into a new directory.

My scrip that I'm trying to use

grep *Qtr_1_results*; cp /data/jobs/file/obj1

I am unable to copy and the output message is:

Usage: cp [-fhipHILPU][-d|-e] [-r|-R] [-E{force|ignore|warn}] [--] src target
       or: cp [-fhipHILPU] [-d|-e] [-r|-R] [-E{force|ignore|warn}] [--] src1 ... srcN directory
Maria Nazari
  • 660
  • 1
  • 9
  • 27
  • [Grep word within a file then copy the file](https://unix.stackexchange.com/q/297006/56041), [How to copy files found with grep](https://stackoverflow.com/q/37396487/608639), [Copying files containing specific text in its content from a folder to other](https://stackoverflow.com/q/18450742/608639), [grep file for string and copy directory to another directory](https://stackoverflow.com/q/38230037/608639), etc. Also see [How much research effort is expected of Stack Overflow users?](http://meta.stackoverflow.com/q/261592/608639) – jww Sep 22 '18 at 07:03
  • @jww Thank you jww! btw, I did research my question before posting, I got myself confused with grep and using cp. – Maria Nazari Sep 24 '18 at 17:04

2 Answers2

6

Edit: After clearing things up (see comment)...

cp *Qtr_1_results* /data/jobs/file/obj1

What you're doing is just greping for nothing. With ; you end the command and cp prints the error message because you only provide the source, not the destination.

What you want to do is the following. First you want to grep for the filename, not the string (which you didn't provide).

grep -l the_string_you_are_looking_for *Qtr_1_results*

The -l option gives you the filename, instead of the line where the_string_you_are_looking_for is found. In this case grep will search in all files where the filename contains Qtr_1_results.

Then you want send the output of grep to a while loop to process it. You do this with a pipe (|). The semicolon ; just ends lines.

grep -l the_string_you_are_looking_for *Qtr_1_results* | while read -r filename; do cp $filename /path/to/your/destination/folder; done

In the while loop read -r will put the output of grep into the variable filename. When you assing a value to a variable you just write the name of the variable. When you want to have the value of the variable, you put a $ in front of it.

fancyPants
  • 50,732
  • 33
  • 89
  • 96
  • I want to pull all files with the name "QTR_1_RESULTS" in it's name, I do not know what to put filename when I do not know the entire filenames. I want to copy several files at once. – Maria Nazari Sep 21 '18 at 22:57
  • 1
    @MariaNazari Oh, I thought you were looking for a string in the file. That's what `grep` is for. Edited my answer. – fancyPants Sep 21 '18 at 23:01
  • For the original answer (string in file, not just in file name) don't forget to put $filename in quotes in case of spaces in the path: `grep -l the_string_you_are_looking_for *Qtr_1_results* | while read -r filename; do cp "$filename" /path/to/your/destination/folder; done` – comodoro Feb 17 '22 at 12:55
2

You can use multiple exec in find to do this task

For eg:

find . -type f -exec grep -lr "Qtr_1_results" {}  \; -exec cp -r {} /data/jobs/file/obj1 \;

Details:

Find all files that contains the string. grep -l will list the files.

find . -type f -exec grep -lr "Qtr_1_results" {} \;

Result set from first part is a list of files. Copy each files from the result to destination.

-exec cp -r {} /data/jobs/file/obj1 \;
Biju
  • 83
  • 5