209

It seems that newer versions of bash have the &> operator, which (if I understand correctly), redirects both stdout and stderr to a file (&>> appends to the file instead, as Adrian clarified).

What's the simplest way to achieve the same thing, but instead piping to another command?

For example, in this line:

cmd-doesnt-respect-difference-between-stdout-and-stderr | grep -i SomeError

I'd like the grep to match on content both in stdout and stderr (effectively, have them combined into one stream).

Note: this question is asking about piping, not redirecting - so it is not a duplicate of the question it's currently marked as a duplicate of.

Andrew Ferrier
  • 15,175
  • 11
  • 42
  • 73
  • See the second answer (https://stackoverflow.com/a/637834/1129642) on the linked question for the correct way to pipe both stdout and stderr. No need for another question. – Marki555 Jul 15 '16 at 08:25
  • 5
    @triplee Not an exact duplicate, is it? Pipe vs. redirect to file? – Benjamin W. Jul 26 '16 at 14:02
  • @BenjaminW There is at least one answer there which solves both scenarios, though it's not the accepted answer. This is a fairly common question so we could probably find a better duplicate, or ask a moderator to merge these - or even, in the worst case, craft an entirely new canonical for this topic. If you find a better dupe, by all means propose it. Thanks in advance. – tripleee Jul 26 '16 at 16:33
  • 14
    @tripleee Solves, yes, but none of the answers use the `|&` shortcut, which I think is by far the most convenient solution to "redirect both stdout and stderr to a pipe". – Benjamin W. Jul 26 '16 at 16:43
  • 3
    This is not a duplicate of the linked question, and it wasn't clear that Marko's answer did what I wanted. Also, it doesn't mention |&. Voting to reopen. – Martin Bonner supports Monica May 05 '17 at 13:23

2 Answers2

206

(Note that &>>file appends to a file while &> would redirect and overwrite a previously existing file.)

To combine stdout and stderr you would redirect the latter to the former using 2>&1. This redirects stderr (file descriptor 2) to stdout (file descriptor 1), e.g.:

$ { echo "stdout"; echo "stderr" 1>&2; } | grep -v std
stderr
$

stdout goes to stdout, stderr goes to stderr. grep only sees stdout, hence stderr prints to the terminal.

On the other hand:

$ { echo "stdout"; echo "stderr" 1>&2; } 2>&1 | grep -v std
$

After writing to both stdout and stderr, 2>&1 redirects stderr back to stdout and grep sees both strings on stdin, thus filters out both.

You can read more about redirection here.

Regarding your example (POSIX):

cmd-doesnt-respect-difference-between-stdout-and-stderr 2>&1 | grep -i SomeError

or, using >=bash-4:

cmd-doesnt-respect-difference-between-stdout-and-stderr |& grep -i SomeError
Adrian Frühwirth
  • 39,348
  • 9
  • 57
  • 69
  • Thanks for the clarification on `&>>`. I've corrected my question. – Andrew Ferrier May 11 '13 at 13:16
  • 19
    I added your example to my answer, just in case it was not obvious based on my given examples. As a side-note, you can also use the bash-specific `|&` instead of `2>&1 |`. – Adrian Frühwirth May 11 '13 at 13:21
  • 14
    Side note about the shortcut `|&` proposed by @AdrianFrühwirth for future readers: this feature is only supported with `bash` version 4+. If you're using 3 or below, you have to stick with `2>&1 |`. – tomocafe Apr 21 '14 at 18:30
  • 3
    Bash redirection is [very well explained here](http://www.catonmat.net/blog/bash-one-liners-explained-part-three/). @AdrianFrühwirth has done a good job, the link pasted goes even further. Sometimes, I wish the official Bash documentation was that good. – David Andreoletti Mar 13 '15 at 03:07
  • @AdrianFrühwirth FYI: your first example references `2>&1` in the description but actually uses `1&2` in the code. – JESii Mar 17 '22 at 22:36
150

Bash has a shorthand for 2>&1 |, namely |&, which pipes both stdout and stderr (see the manual):

cmd-doesnt-respect-difference-between-stdout-and-stderr |& grep -i SomeError

This was introduced in Bash 4.0, see the release notes.

Benjamin W.
  • 38,596
  • 16
  • 96
  • 104
  • 1
    Thanks for adding this for completeness. I'm going to keep the other answer correct as many folks are still using bash pre-4.0. But this is useful. – Andrew Ferrier May 09 '16 at 09:30
  • 13
    Most notably perhaps, the Bash that ships on macOS is too old to support this. – Flimm Jan 20 '17 at 10:21
  • 1
    @Flimm but the zsh isn't – Trenton Feb 13 '17 at 21:41
  • 1
    Since ksh uses |& for coproc, this seems like a bad choice for an unnecessary shorthand. I hate to see lines with a stack of dups and redirections as much as the next guy, but there's something to be said for being explicit....and I apologize that this comment doesn't add much. I just wanted to express distaste for the shorthand without downvoting an actually helpful answer, because it's good that people see this. I didn't know this, so thanks for making me aware. – Paul Hodges Oct 02 '17 at 14:59
  • 1
    @PaulHodges I agree that it's not portable - I mainly like using it for interactive Bash sessions to avoid typing too much. – Benjamin W. Oct 02 '17 at 16:40