Reputation: 1315
Take the following bash script:
#!/bin/bash
ls /sdfg
if [ $? -gt 0 ]
then
echo "Command failed: $?"
else
echo "Command succeeded: $?"
fi
The output will be:
ls: cannot access /sdfg: No such file or directory
Command failed: 0
The failed ls command actually returns 2, the if statement catches this, and echos command failed, but why does $? get updated to zero? It looks like the if/then lines are being treated as a new command.
Upvotes: 1
Views: 1648
Reputation: 295619
Collect the return value immediately after the command being tested if you're going to reuse it:
#!/bin/bash
# best-practice: collect *on the same line*, so any logging added in the future doesn't
# ...change your exit status.
ls /sdfg; retval=$?
if [ $retval -gt 0 ]; then
echo "Command failed: $retval" #
else
echo "Command succeeded: $retval"
fi
However, the best practice is to directly operate on the command's exit status without needing to refer to $?
at all:
if ls /sdfg; then
echo "Command succeeded: $?"
else
echo "Command failed: $?"
fi
Upvotes: 1
Reputation: 189628
You should rarely need to examine $?
explicitly anyway, since doing that is the purpose of if
(and other conditional builtins like while
). The proper way to write that is
if ls /sdfg; then
echo "Command succeeded: $?"
else
echo "Command failed: $?"
fi
Notice how the failure case is now the else
branch. (If you don't particularly care about preserving the failure exit code, you can use if ! ls
... and keep the success branch in the else
, but your question seems to be specifically about preserving it, which negation with !
will not do.)
Upvotes: 2
Reputation: 360762
[
is actually a binary, not just some punctuation:
$ ls -l /usr/bin/[
-rwxr-xr-x 1 root root 51920 Feb 18 07:37 /usr/bin/[
$ /usr/bin/[ --version
[ (GNU coreutils) 8.25
Copyright (C) 2016 Free Software Foundation, Inc.
and on some systems may be a symlink to test
.
So here
if [ $? -gt 0 ]
$?
is the result of your ls
call, but here
echo "Command failed: $?"
$?
is the result of having executed [
on the previous line.
If you want to test $?
from a command multiple times, you'll have to stuff it into a temp var:
ls blahblah
temp=$?
if [ $temp ... ]
if [ $temp ... ]
Upvotes: 2