Append output of one command to the output of anot

2019-07-10 10:43发布

问题:

Is there a way to append the stdout output of one command to another's and pipe the combined output to another command? I used to use the following approach(taking ack-grep as an example)

# List all python, js files in different directories
ack-grep -f --py apps/ > temp
ack-grep -f --js -f media/js >> temp
cat temp | xargs somecommand

Is there a way to do this in a single command?

回答1:

Just run the two ack-grep commands as a compound command; then pipe the results of the compund command. The first compound command defined in man bash is the parentheses:

   (list) list is executed in a subshell environment (see  COMMAND  EXECU-
              TION  ENVIRONMENT below).  Variable assignments and builtin com-
              mands that affect the  shell's  environment  do  not  remain  in
              effect  after  the  command completes.  The return status is the
              exit status of list.

So:

james@bodacious-wired:tmp$echo one > one.txt
james@bodacious-wired:tmp$echo two > two.txt
james@bodacious-wired:tmp$(cat one.txt; cat two.txt) | xargs echo
one two

You can use curly braces to similar effect, but curly braces have a few syntactical differences (they're more finicky about needing spaces between the brace and other words, for instance). The biggest difference is that the commands inside braces are run in the current shell environment, so they can impact on your environment. For instance:

james@bodacious-wired:tmp$HELLO=world; (HELLO=MyFriend); echo $HELLO
world
james@bodacious-wired:tmp$HELLO=world; { HELLO=MyFriend; }; echo $HELLO
MyFriend

If you want to get really fancy you can define a function and execute that:

james@bodacious-wired:tmp$myfunc () (
> cat one.txt
> cat two.txt
> )
james@bodacious-wired:tmp$myfunc | xargs echo
one two
james@bodacious-wired:tmp$


回答2:

Group the two commands in curly braces and pipe them:

{ ack-grep -f --py apps/; ack-grep -f --js -f media/js; } | xargs somecommand

This way you omit the creation of any files.



回答3:

May be something like this:

ack-grep -f --py apps/ > temp && ack-grep -f --js -f media/js >> temp && cat temp | xargs somecommand


回答4:

Yes, use find. According to the ack-grep man page those options just look for .py and .js files

find apps/ media/js -type f -name "*.py" -o -name "*.js" -exec somecommand {} +

The + option to -exec makes it work just like xargs but with the benefit that it doesn't die a horrible death if you have files with spaces or newlines or other nasties in their name.