This question already has an answer here:

The command:

grep -rl "KORD" ./

searches a directory and returns a list of files containing "KORD" in the file contents (not the title).

Users-MacBook-Air:myPhotorec user$ grep -rl "KORD" ./

Is there a preferred command(xargs?) that augment the grep command to print the output file list to the console and copy each file to the a directory: ./ORD ?

I suspect that there is more than one way to 'skin a cat': I am looking forward to seeing more than one solution

JOHN1024's XARGS Solution

The duplicate label prevents posting this modified posting as answer:


grep -rl --null --include '*.txt' KORD . | xargs -0r cp -t /path/to/dest

Because this command uses NUL-separation, it is safe for all file names including those with difficult names that include blanks, tabs, or even newlines.

The above requires GNU cp. For BSD/OSX, try:

grep -rl --null --include '*.txt' KORD . | xargs -0 sh -c 'cp "$@" /path/to/dest' sh

How it works:

  1. grep options and arguments

    • -r tells grep to search recursively through the directory structure. (On FreeBSD, -r will follow symlinks into directories. This is not true of either OS/X or recent versions of GNU grep.)

    • --include '*.txt' tells grep to only return files whose names match the glob *.txt (including hidden ones like .foo.txt or .txt).

    • -l tells grep to only return the names of matching files, not the match itself.

    • --null tells grep to use NUL characters to separate the file names.

    • LINUX/UNIX tells grep to look only for files whose contents include the regex LINUX/UNIX

    • . search in the current directory. You can omit it in recent versions of GNU grep, but then you'd need to pass a -- option terminator to cp to guard against file names that start with -.

  2. xargs options and arguments

    • -0 tells xargs to expect NUL-separated input.

    • -r tells xargs not to run the command unless at least one file was found. (This option is not needed on either BSD or OSX and is not compatible with OSX's xargs.)

    • cp -t /path/to/dest copies the directories to the target directory. (-t requires GNU cp.)

marked as duplicate by don_crissti, Kusalananda, Stéphane Chazelas grep May 5 '18 at 20:38

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • The whole point of closing one question as a duplicate of another is to say that the two questions are the same, and so any answer(s) to the other one will also answer this one. So why would you copy an answer from the other question into your question?  It’s pointless. – Scott May 6 '18 at 1:32
  • Unfortunately, there is no discussion in the linked solution as to the throught process as to which of the two solution is preferable. Only the how is explained and not why. Adding the xargs solution to the OP removes the how-to question from the discussion. – gatorback May 6 '18 at 14:08
find . -type f -exec grep -q 'KORD' {} ';' -exec cp {} ./ORD ';'

This would find all regular files in or below the current directory. grep -q 'KORD' would be run on each file, and the files that contains matching lines would be copied to the directory ./ORD.

If you have GNU coreutils installed, then you may use the slightly more efficient

find . -type f -exec grep -q 'KORD' {} ';' -exec cp -t ./ORD {} +

See also: Understanding the -exec option of `find`

  • An elegant solution. See JOHN1024's XARGS Solution (above) for easy / concise explanation format. – gatorback May 5 '18 at 22:36
  • @gatorback Note my comment to that solution, --null does not work on all Unix systems, and neither does --include. My (first) solution above is portable. The second has a dependency an GNU coreutils. – Kusalananda May 5 '18 at 22:52

Not the answer you're looking for? Browse other questions tagged or ask your own question.