aggu
aggu

Reputation: 93

Zsh output redirection behavior

In bash:

bash% echo xxx >&2 | wc
xxx
   0   0   0

In zsh:

zsh% echo xxx >&2 | wc
xxx
   1   1   4
zsh% { echo xxx >&2; } | wc
xxx
   0   0   0

How do I make zsh behave like bash for this case? Is there a zsh option to set?

Upvotes: 3

Views: 422

Answers (2)

mklement0
mklement0

Reputation: 438178

To change the behavior ad-hoc, you can simply parenthesize:

(echo xxx >&2) | wc

Note that there is no side effect from parenthesizing here, as even without it your commands run in subshells, due to use of a pipe (|).

To change the behavior for the entire shell, see @chepner's answer.


Performance considerations:

@chepner asks in a comment whether the parentheses result in an additional subshell (and thus child process).

The surprising answer is the opposite:
With option MULTIOS ON (the default), using parentheses results in 1 fewer subshell.

With option MULTIOS OFF, the parentheses (which are then not needed) make no difference.


How I tested:

On OS X 10.9.2, I used sudo dtruss -t fork -f -p {pidOfZsh} to monitor fork() calls in a zsh shell; zsh version is zsh 5.0.2 (x86_64-apple-darwin13.0).

With option MULTIOS ON, echo xxx >&2 | wc forked 3 times, while (echo xxx >&2) | wc only forked 2 times.

Upvotes: 4

chepner
chepner

Reputation: 531345

Turning off the MULTIOS option changes this behavior.

% echo xxx >&2 | wc
xxx
       1       1       4
% setopt NOMULTIOS
% echo xxx >&2 | wc
xxx
       0       0       0

With the option set, a single command can have multiple IO redirections, and for this purpose, it appears the pipe counts as one.

Upvotes: 3

Related Questions