Combine the output of two commands in bash

Is it possible to combine output from these two commands?

node ~/projects/trunk/index.js 
python ~/projects/trunk/run.py run

Neither command exits so I’m not sure how to do this.

Asked By: chovy

||

You can combine two commands by grouping it with { } :

{ command1 & command2; }

so far, you can redirect the group to a file (last ; before } is mandatory), and the space between the open and closing bracket too.

{ command1 & command2; } > new_file

if you want to separate STDOUT and STDERRin two files :

{ command1 & command2; } > STDOUT_file 2> STDERR_file

If you don’t want to run the first command in the background, use this form :

{ command1; command2; }

or

{ command1 && command2; }

to run the second command only if the first is a success

Answered By: Gilles Quenot

Try this:

paste $(node ~/projects/trunk/index.js) $(python ~/projects/trunk/run.py run) > outputfile
Answered By: frogstarr78

I ended up doing this, the other suggestions did not work, as the 2nd command was either killed or never executed.

alias app () {
    nohup python ~/projects/trunk/run.py run 1>/tmp/log 2>&1 &
    echo $! > /tmp/api.pid
    nohup node ~/projects/trunk/index.js 1>/tmp/log 2>&1 &
    echo $! > /tmp/client.pid
    tail -f /tmp/log
}
Answered By: chovy

More generally, it’s possible to use either a subshell or command grouping, and redirect the output of the whole group at once.

Code:

( command1 ; command2 ; command3 ) | cat

{ command1 ; command2 ; command3 ; } > outfile.txt

The main difference between the two is that the first one splits of a child process, while the second one operates in the context of the main shell. This can have consequences regarding the setting and use of variables and other environment settings, as well as performance.

Don’t forget that the closing bracket in command grouping (and functions) must be separated from the contents by either a semicolon or a newline. This is because "}" is actually a command (keyword) of its own, and must be treated like one.

Answered By: j9s

Most of the solutions so far deal badly with the partial line problem. Assume for a second that the programs are:

cmd1() {
    perl -e 'while(1) { print "a"x3000_000,"n"}'
}
export -f cmd1
cmd2() {
    perl -e 'while(1) { print "b"x3000_000,"n"}'
}
export -f cmd2

When running those in parallel you want the output to have full lines of as followed by full lines of bs. What you do not want is as and bs mixing on the same line (tr -s ab replaces repeating as with a single a, so it is easier to see what happens):

# This is bad - half lines are mixed
$ (cmd1 & cmd2 ) | tr -s ab
bababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababa
ababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababab

If you instead use GNU Parallel, you get nice clean full lines with either as or bs but never mixed:

$ parallel --line-buffer ::: cmd1 cmd2 | tr -s ab
a
a
b
b
b
b
a

Newer versions of GNU Parallel even avoids filling up your disk: The above can run forever.

Answered By: Ole Tange

Since you’re already using node, you may want to try concurrently

Run multiple commands concurrently. Like npm run watch-js & npm run watch-less but better.

Answered By: Tamlyn

For the special case of combining multiple BASH command outputs onto one line, here’s a recipe to run each command in turn, removing any newlines between their outputs.

(echo 'ab' && echo 'cd' && echo 'ef') | tr -d 'n'
>>> abcdef

As a real-world example, the code below will embed an ASCII message between two fixed strings of bytes (forming a print command, in this case)

#   hex prefix           encode a message as hex    hex suffix    | strip newline | hex to binary | (then, for example, send the binary over a TCP connection)
(echo '1b40' && echo "Test print #1" | xxd -p && echo '1d564103') | tr -d 'n'    | xxd -r -p     | nc -N 192.168.192.168 9100

(Note: this method only works if the commands exit. For combining stdout from commands that don’t exit, see other answers.)

Answered By: Luke

The accepted answer’s output might not come in the right order, do not use it if your sources are async (e.g. cat or curl)

Use this instead:

cat <(command1) <(command2) <(command3) > output.txt

Real life example:

cat 
<(curl https://stackoverflow.com/humans.txt) 
<(echo -e "nnDownloaded from https://stackoverflow.com") 
> output.md

Produces

There's a bunch of humans behind Stack Overflow and the network of Stack Exchange sites. If you'd like to join us check out https://stackoverflow.com/company/work-here

Downloaded from https://stackoverflow.com
Answered By: fregante

Parallel vs Serial execution:
It is important to highlight the two different solutions:

  1. Parallel Execution, use e.g. ‘&’ as in (cmd1)&(cmd2)
  2. Serial Execution, use e.g. ‘&&’ as in (cmd1)&&(cmd2)
  3. Serial Execution, where you want the second task to be executed even if the first one fails, use e.g. ‘;’ as in (cmd1;cmd2)

Proof / example for (1) vs (2):

$ (echo p1;sleep 6;echo p1-end) && (echo p2;sleep 6;echo p2-end)
p1
p1-end
p2
p2-end
$ (echo p1;sleep 6;echo p1-end) & (echo p2;sleep 6;echo p2-end)
[1] 104629
p1
p2
p1-end
p2-end
Answered By: ntg
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.