Tuesday, August 16, 2005

Bash - Careful while using $?

The exit status of a command can be obtained using the shell variable $?. In other words, $? contains the exit status of the preceding command. But there are some cases when using this carelessly can cause errors.
One such scenario in which using this can be a problem is when there are multiple exit values possible. For example:

/bin/ls * > /home/karthick/lsfile 2>&1
if [ $? -eq 0 ]
 echo "Hello"
elif [ $? -eq 1 ]
 echo "Hi"
 echo "Bye"
This must work in most cases. But consider this:
$ ls *
bash: /bin/ls: Argument list too long
$ echo $?
In this case the output of the script is expected to be Bye. But it gives the output Hi. Not only in this case, in all cases in which the exit status of ls is not 0, it will output Hi.
This is because, the condition $? -eq 0 is considered to be a command and hence the condition in elif checks the exit status of $? -eq 0, which is 1 (Failure - Remember the exit status of ls is 126). Hence the output of this script would be 126.
In cases where we need to multiple value checks, there are two ways of doing it safely.
  1. Use case...esac.
  2. Store the exit status of the command in a variable and use the variable in the conditions.