Is there any way, in bash, to pipe STDERR through a filter before unifying it with STDOUT? That is, I want
STDOUT ────────────────┐
├─────> terminal/file/whatever
STDERR ── [ filter ] ──┘
rather than
STDOUT ────┐
├────[ filter ]───> terminal/file/whatever
STDERR ────┘
A naive use of process substitution seems to allow filtering of
stderr
separately fromstdout
:Note that
stderr
comes out onstderr
andstdout
onstdout
, which we can see by wrapping the whole thing in another subshell and redirecting to fileso
ande
Take a look at named pipes:
I find the use of bash process substitution easier to remember and use as it reflects the original intention almost verbatim. For example:
uses the first sed command as a filter on stderr only and the second sed command to modify the joined output.
Note that the white space after 2> is mandatory for the command to be parsed correctly.
The last part of this page of the Advanced Bash Scripting Guide is "redirecting only stderr to a pipe".
This may be what you want. If not, some other part of the ABSG should be able to help you, it is excellent.
TL;DR:
Example:
This will work in both bash and zsh. Bash is pretty much ubiquitous these days, however, if you really do need a (really gnarly) solution for POSIX
sh
, then see here.Explanation
By far, the easiest way to do this is to redirect STDERR via process substitution:
So what you get with process substituion is a filename.
Just like you could do:
you can do
The
>&2
redirect'sfilter
's STDOUT back to the original STDERR.TL;DR: (bash and zsh)
Example:
Many answers on the StackExchange network have the form:
This has a built-in assumption: that file descriptor 3 isn't being used for something else.
Instead, use a named file descriptor, and
{ba,z}sh
will allocate the next available file descriptor >= 10:Note that named file descriptors aren't supported by POSIX
sh
.The other issue with the above is that the command cannot be piped to further commands without again swapping STDOUT and STDERR back to their original values.
To allow onward piping in POSIX
sh
, (and still assuming FD 3 is not it use) it gets complicated:So, Given the assumption and gnarly syntax of this, you're likely to be better off using the simpler
bash
/zsh
syntax shown in the TL;DR above, and explained here.