Zsh – How to Pipe Only Stderr in Zsh

io-redirectionpipeshellstderrzsh

In bash:

$ echo hi 2>&1 1>/dev/null | cat
$

While in zsh:

$ echo hi 2>&1 1>/dev/null | cat
hi
$

Is there a way to pipe only standard error while redirecting standard out?

Best Answer

With zsh and with the mult_ios option on (on by default), in:

echo hi 2>&1 1>/dev/null | cat

The 1> /dev/null | cat is seen as a multiple redirection of echo's stdout.

So echo's stdout is now redirected to both /dev/null and a pipe to cat (as if using tee).

To cancel that multiple redirection, you can do:

echo hi 2>&1 >&- > /dev/null | cat

That is, closing stdout (cancelling the piping) before redirecting to /dev/null

Or use a command group or subshell like:

{echo hi 2>&1 1>/dev/null} | cat 
(echo hi 2>&1 1>/dev/null) | cat

That way, echo's stdout is only redirected explicitly once (the pipe redirection is applied to the group/subshell and inherited by echo).

Or you can disable multios altogether:

(setopt nomultios; echo hi 2>&1 > /dev/null | cat)

Alternatively, you could use process substitution instead of a pipe:

echo hi 2> >(cat) > /dev/null

Beware however that when job control is off (like in scripts), the cat process will be running asynchronously (as if started with &).

Related Question