I was a bit disturbed to find the following behavior:
bash$ false
bash$ true | echo $?
0
bash$ ksh
ksh$ false
ksh$ true | echo $?
0
ksh$ zsh
zsh$ false
zsh$ true | echo $?
1
Intuitively, it looks like zsh gets it right while bash and ksh are wrong. $?
is 'the exit status of the most recently executed pipeline', which in each case should be 1. Note that false | echo $?
also prints 0 in both ksh
and bash
. Is the standard flexible on this point (ie, the behavior is unspecified), or are bash
and ksh
non-compliant here? I'm also curious to know what bash and ksh are doing to get this wrong.
$ bash --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin11)
Copyright (C) 2007 Free Software Foundation, Inc.
$ zsh --version
zsh 4.3.11 (i386-apple-darwin11.0)
$ ksh --version
version sh (AT&T Research) 1993-12-28 s+
POSIX says:
$? Expands to the decimal exit status of the most recent [command or] pipeline ...
Please note the comment from @lurker. Bash in it's current version 4.3.11
behaves the same as zsh
.
What happens in bash
and zsh
is that $?
will be set by the command before the pipe and get not changed inside the pipe. That's why the expected the result is the return value from false
-> 1
. And this is what POSIX specifies.
I couldn't find any documentation that describes the ksh
behaviour. I can only assume that ksh
resets $?
before executing the pipe, since the following code works:
#!/bin/ksh
false
ret=$?
true | echo "$ret"
Probably this should get filed as a bug in ksh
. However, I'm not sure if this behaviour is specified exactly enough by POSIX.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With