Reading the manual of the test
shell command:
man test
Description states:
Exit with the status determined by EXPRESSION.
But this conflicts with my POSIX sh test script examples, where I use set -eu
that should terminate a script if a command's exit status is not zero:
#!/bin/sh
set -eu
status=1
test "$status" -ne 0 && echo "Status not eq 0"
echo "(A) Exit code for "$status" = $?"
echo ""
status=0
test "$status" -ne 0 && echo "Status not eq 0"
echo "(B) Exit code for "$status" = $?"
echo ""
status=1
test "$status" -ne 0
echo "(C) Exit code for "$status" = $?"
echo ""
status=0
test "$status" -ne 0
echo "(D) Exit code for "$status" = $?"
running that script provides the output:
Status not eq 0
(A) Exit code for 1 = 0
(B) Exit code for 0 = 1
(C) Exit code for 1 = 0
This is how I understand flow of a execution for:
status=1
test "$status" -ne 0 && echo "Status not eq 0"
echo "(A) Exit code for "$status" = $?"
with output:
Status not eq 0
(A) Exit code for 1 = 0
test "$status" -ne 0
evaluates to true so its exit code is zero therefore an expression after boolean &&
is executed and since it is just an echo
it returns also zero exit code so the script does not brake and echoes next line (A) Exit code for 1 = 0
but for the
status=0
test "$status" -ne 0 && echo "Status not eq 0"
echo "(B) Exit code for "$status" = $?"
with the output:
(B) Exit code for 0 = 1
Following previous reasoning the test
should return non zero therefore an expression after &&
should not be executed (and it is not) but the script executes even the test
returned non zero exit code (B) Exit code for 0 = 1.
Why does the script continue execution? It should brake due to non zero exit status.
There is no output for the case:
status=0
test "$status" -ne 0
echo "(D) Exit code for "$status" = $?"
that suggests to me the script execution was terminated at the line test "$status" -ne 0
and if you run echo $?
after running the script you'll get in fact 1
.
But how come the script is terminated when the test returns non zero exit status for the example (D) but it is not for the example (B)?
The only difference between (D) and (B) is that (B) has && echo "Status not eq 0"
after the test but that is not executed and the exit status is 1
so in case of (B) the script should be terminated but it wasn't and if an exit status of a test is treated somehow so specially so it does not terminate a script having a set -e
then why it terminates script for the (D) example?
EDIT
Similarly to test
behaves ls
for the script:
#!/bin/sh
set -eu
ls notexitingfile && echo "File exists"
echo "Exit code for ls = $?"
ls notexitingfile
echo "Exit code for ls = $?"
the output is:
ls: cannot access 'notexitingfile': No such file or directory
Exit code for ls = 2
ls: cannot access 'notexitingfile': No such file or directory
note Exit code for ls = 2
for the first example and lack of it for the second.
I think the cause of the unexpected behavior may be my misunderstanding of the script termination (set -e
) due to non zero exit code when using &&
operator.