Reputation: 349
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
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
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