78

How can I pipe the stdout of multiple commands to a single command?

Example 1: combine and sort the output of all three echo commands:

echo zzz; echo aaa; echo kkk

desired output:

aaa
kkk
zzz

Example 2: rewrite the following so that all the commands are in a single command-line using pipes, without redirects to a temp file:

setopt > /tmp/foo; unsetopt >> /tmp/foo; set >> /tmp/foo; sort /tmp/foo
Rob Bednark
  • 25,981
  • 23
  • 80
  • 125

3 Answers3

110

Use parentheses ()'s to combine the commands into a single process, which will concatenate the stdout of each of them.

Example 1 (note that $ is the shell prompt):

$ (echo zzz; echo aaa; echo kkk) | sort
aaa
kkk
zzz


Example 2:

(setopt; unsetopt; set) | sort
Rob Bednark
  • 25,981
  • 23
  • 80
  • 125
  • 9
    @glenn: that doesn't matter (tested in bash 3.2.48), since the pipeline forces it into a subshell anyway. – Gordon Davisson Aug 12 '12 at 14:25
  • 3
    @KennyEvitt Check the [pipeline section](https://www.gnu.org/software/bash/manual/bash.html#Pipelines): "Each command in a pipeline is executed in its own subshell...". Actually, this can be changed with [`shopt -s lastpipe`](https://www.gnu.org/software/bash/manual/bash.html#The-Shopt-Builtin), which runs the *last* section of a pipeline in the current shell. But in this case it's the first section we're concerned with, so it'd still run in a subshell. – Gordon Davisson Mar 29 '17 at 20:27
  • 3
    @KennyEvitt It seems to coalesce them into a single level of subshell (at least under bash, test w/ versions 2.05b.0, 3.2.57, and 4.2.10; other shells may differ). But when I use `{ ( echo zzz; echo aaa; echo kkk ) } | sort` I do get the extra subshell. – Gordon Davisson Mar 30 '17 at 17:23
29

You can use {} for this and eliminate the need for a sub-shell as in (list), like so:

{ echo zzz; echo aaa; echo kkk; } | sort

We do need a whitespace character after { and before }. We also need the last ; when the sequence is written on a single line.

We could also write it on multiple lines without the need for any ;:

Example 1:

{
  echo zzz
  echo aaa
  echo kkk
} | sort

Example 2:

{
  setopt
  unsetopt
  set
} | sort
codeforester
  • 39,467
  • 16
  • 112
  • 140
3

In Windows it would be as follow: (echo zzz & echo aaa & echo kkk) | sort

Or if it is inside a batch file it can be mono line (like sample) as well as multiline:

(
 echo zzz
 echo aaa
 echo kkk
) | sort

Note: The original post does not mention it is only for Linux, so I added the solution for Windows command line... it is very useful when working with VHD/VHDX with diskpart inside scripts (echo diskpart_command) instead of the echo on the same, but let there the echo, there is also another way without echos and with > redirector, but it is very prone to errors and much more complex to write (why use a complicated prone to errors way if exists a simple way that allways work well)... also remember %d% gives you the actual path (very useful for not hardcoding the path of VHD/VHDX files).

Drigan
  • 200
  • 3
  • 14
Claudio
  • 39
  • 1