Jason Hemann
Jason Hemann

Reputation: 349

How to copy files found with grep on OSX

I'm wanting to copy files I've found with grep on an OSX system, where the cp command doesn't have a -t option.

A previous posts' solution for doing something like this relied on the -t flag in cp. However, like that poster, I want to take the file list I receive from grep and then execute a command over it, something like:

grep -lr "foo" --include=*.txt * 2>/dev/null | xargs cp -t /path/to/targetdir

Upvotes: 4

Views: 2499

Answers (2)

Jason Hemann
Jason Hemann

Reputation: 349

Yet another option is, if you have admin privileges or can persuade your sysadmin, to install the coreutils package as suggested here, and follow the steps but for cp rather than ls.

Upvotes: 0

webb
webb

Reputation: 4340

Less efficient than cp -t, but this works:

grep -lr "foo" --include=*.txt * 2>/dev/null |
  xargs -I{} cp "{}" /path/to/targetdir

Explanation:

For filenames | xargs cp -t destination, xargs changes the incoming filenames into this format:

cp -t destination filename1 ... filenameN

i.e., it only runs cp once (actually, once for every few thousand filenames -- xargs breaks the command line up if it would be too long for the shell).

For filenames | xargs -I{} cp "{}" destination, on the other hand, xargs changes the incoming filenames into this format:

cp "filename1" destination
...
cp "filenameN" destination

i.e., it runs cp once for each incoming filename, which is much slower. For a large number (e.g., >10k) of very small (e.g., <10k) files, I'd guess it could even be thousands of times slower. But it does work :)

PS: Another popular technique is use find's exec function instead of xargs, e.g., https://stackoverflow.com/a/5241677/1563960

Upvotes: 2

Related Questions