piping standard error

I’ve often wished I could pipe only standard error to a command, leaving standard out to display on the screen as is. One place this would be useful, the one that finally got me to act, is to make compiler warnings show up in a different color, to make them more noticeable.

I decided grep ".*" would work quite well for coloring things, since I have --color=AUTO on by default. The problem, though, was how could I get standard error to go to grep instead of standard out? (I have green text on a black background, and grep turns what it matches red. If I piped standard out to grep ".*", I’d get red text with green errors, and that’s just backwards :P)

The internet wasn’t very helpful. It gave me a bunch of things halfway there, like redirecting standard error to standard out, and even saving standard out as a file and redirecting standard error to standard out and piping that, but I wanted standard error to stay standard error, standard out to stay standard out, and them both displayed on screen like normal, only with stderr having been run through a command.

So, of course, I had to do it myself.

Here’s what I came up with: (command 2>&1 1>&3 | grep ".*" 1>&2) 3>&1

So how’s this work? Well, first stdout (file handle 1) is redirected to file handle 3. Yes, that’s first. Apparently they’re evaluated in backwards order. Took me a while to figure that out. Then stderr (file handle 2) is redirected to stdout (file handle 1). Then it’s piped to grep (or whatever command you want, I could see useful things being done with sed here) and the output sent back to stderr, and then finally file handle 3, the original stdout, is sent back to stdout.

I hope someone finds this useful. I know I will!

Comments are closed.