Bash test on successful subshell command returns false

bashtest

I don't quite understand this behaviour of bash test operator. I used this line to determine if vagrant is installed.

if [ $(vagrant --version > /dev/null) ]; then echo "HELLO"; fi

I now know that this returns false (1) and that you should type only

if vagrant --version > /dev/null; then echo "HELLO"; fi

to get the expected result. But I still don't understand why [ $(vagrant –version > /dev/null) ] returns false (1). Shouldn't it return true (0) since

$(vagrant --version > /dev/null)

returns true, which is an expression (isn't it?).

From test man page:

The test utility evaluates the expression and, if it evaluates to true, returns a zero (true) exit status; otherwise it returns 1 (false). If there is no
expression, test also returns 1 (false).

Best Answer

All these are equivalent:

[ $(vagrant --version > /dev/null) ]
[ ]
test

shells are not like other programming languages. They have 2 outputs: The return value, and stdout. You are passing stdout to test, but stdout is the empty string, as it has been redirected.

What you were looking for is.

[ $(vagrant --version > /dev/null; echo $? ) ]

However [ 0 ] and [ 1 ] etc all return true because [ … ] with a single word inside tests if the word is non-empty. So you need

[ $(vagrant --version > /dev/null; echo $? ) = 0 ]

or more simply

vagrant --version > /dev/null