Why does `if $(true) ; then ... fi` succeed? Why does `if $(true) ; then ... fi` succeed? bash bash

Why does `if $(true) ; then ... fi` succeed?


See section 2.9.1 of the language spec. The last sentence of the first section reads:

If there is a command name, execution shall continue as described in Command Search and Execution . If there is no command name, but the command contained a command substitution, the command shall complete with the exit status of the last command substitution performed. Otherwise, the command shall complete with a zero exit status.

The $(true) is expanding to the empty string. The shell parses the empty string and finds that no command is given and follows the above rule.


There are potentially two exit codes to consider. First, here's another two experiments that should help:

# if $(echo true; false) ; then echo yes ; else echo no ; fiyes

The inner command exits with failure because of the false. But that's irrelevant because the output of the command is non-empty and hence the output ("true") is executed instead and its exit code takes priority.

# if $(echo false; true) ; then echo yes ; else echo no ; fino

Again, the command line inside the $( ) is successful, but the output is no because the output ("false") takes priority.

The exit status of the commands inside the $( ) is relevant if and only if the output is empty or only whitespace. If the output is empty, there is no list of commands to execute and hence it appears that the shell will fall back on the exit status of the inner command.


What appears to be happening is that bash keeps the exit status of the last executed command

This would explain why $(true) and $(false) have different behavior in an if test. They both produce null commands which doesn't count as execution but they have different exit codes.

As soon as you use command substitution on a command that has output, $() attempts to execute that output as a command and the exit code of that attempt is now the latest one used for the if test