I’m getting confused with using the test command inside a script. Normally I am experienced with Linux but lately I was not able to get my head around the following problem:
I want to check if a directory exists by using test -d dir. Depending if the directory exists or not I want to return a echo output. So the if statement will look somewhat like this:
if test -d $HOME/dir
then
echo $?
echo The directory exists.
else
echo $?
echo The directory does not exist.
fi
My problem now is understanding the error codes. Why does the if statement go into the condition True block when the error code of the test command is 0?
From my understanding it should be the other way around, especially if I don’t specify a condition but simply use if test ….
I have read the man file of test but I wasn’t getting any smarter. In addition I tested to use a condition for the if statement like this:
test -d $HOME/dir
exitcode=$(echo $?)
if [ "$exitcode" -ne 0 ]
then
echo -e exit is $exitcode
echo -e does not exist
else
echo -e exit is $exitcode
echo -e exists
fi
exit
Of course both scripts return the same output, but again: I don’t know why using the test command together with the if statement makes the if statement go inside the condition true block when the exit code is 0.
>Solution :
You are thinking about this slightly backwards. if doesn’t test Boolean expressions. (The shell itself doesn’t have Boolean expressions to test.) if always executes a command and checks for a zero-vs-non-zero exit status.
[ itself is just a synonym for test, and test is a command that basically uses a mini-language to construct a Boolean expression from its arguments, evaluates that expression, then exits 0 if the expression is true, and 1 if it is false.
The convention is opposite that used by C and C-like languages, where 1 is true and 0 is false. Because a command typically can succeed in one way, but fail in may different ways, we use the unique non-positive value 0 to indicate success, but different positive values to indicate failure. It is a further convention that 1 itself represents a general error, but many commands use different non-zero exit status to indicate different errors. Sometimes, you care about a distinction between 1 and 2, other times you don’t. When you do, you can use a case statement to distinguish them. For example,
grep "$some_regex" foo.txt
case $? in
0) echo "regex matched"
1) echo "regex did not match"
*) echo "some error running grep, we don't know if the regex matches or not"
esac