xargs with multiple commands
Answer #1 93.7 %To start with, there is virtually no difference between:
find . | grep "file_for_print" | xargs echo
and
find . -name "file_for_print*"
except that the second one will not match filenames like this_is_not_the_file_for_print
, and it will print the filenames one per line. It will also be a lot faster, because it doesn't need to generate and print the entire recursive directory structure just in order for grep to toss most of it away.
find . -name "file_for_print*"
is actually exactly the same as
find . -name "file_for_print*" -print
where the -print
action prints each matched filename followed by a newline. If you don't provide find
with any actions, it assumes you wanted -print
. But it has more tricks up its sleeve than that. For example:
find . -name "file_for_print*" -exec cat {} \;
The -exec
action causes find to execute the following command, up to the \;
, replacing {}
with each matching file name.
find
does not limit itself to a single action. You can tell it to do however many you want. So:
find . -name "file_for_print*" -print -exec cat {} \;
will probably do pretty well what you want.
For lots more information on this very useful utility, type:
man find
or
info find
and read all about It.
Answer #2 100 %find . | grep "file_for_print" | xargs -I % sh -c 'echo %; cat %;'
(OP was missing %
s)
Since it's not been said yet: -I %
tells xargs to replace '%' with the arguments in the command you give it. The sh -c '...'
just means run the commands '...'
in a new shell.
So
xargs -I % sh -c 'echo %; cat %;'
will run echo [filename]
followed by cat [filename]
for every filename given to xargs
. The echo and cat commands will be executed inside a different shell process but this usually doesn't matter. Your version didn't work because it was missing the %
signs inside the command passed to xargs
.
For what it's worth I would use this command to achieve the same thing:
find -name "*file_for_print*" | parallel 'echo {}; cat {};'
because it's simpler (parallel
automatically uses {}
as the substitution character and can take multiple commands by default).