Combine the output of two commands in bash
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 STDERR
in two files :
{ command1 & command2; } > STDOUT_file 2> STDERR_file
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.
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 a
s followed by full lines of b
s. What you do not want is a
s and b
s mixing on the same line (tr -s ab
replaces repeating a
s 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 a
s or b
s 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.