Por que `if $ (true); então ... fi` conseguiu?

Inspirado poressa questã:

O que uma instrução if deve fazer quando a condição é uma substituição de comando em que o comando não produz saíd

NOTA O exemplo éif $(true); then ..., nãoif true ; then ...

Por exemplo, dado:

if $(true) ; then echo yes ; else echo no ; fi

Eu pensaria que$(true) deve ser substituído pela saída dotrue comando, o que não é nada. Em seguida, deve ser equivalente a isso:

if "" ; then echo yes ; else echo no ; fi

which imprimeno porque não existe um comando cujo nome seja a string vazia ou para isso:

if ; then echo yes ; else echo no ; fi

que é um erro de sintax

Mas a experiência mostra que, se o comando não produzir saída, oif instrução @ trata como verdadeira ou falsa, dependendo do status do comando, e não da saíd

Aqui está um script que demonstra o comportamento:

#!/bin/bash

echo -n 'true:          ' ; if true          ; then echo yes ; else echo no ; fi
echo -n 'false:         ' ; if false         ; then echo yes ; else echo no ; fi
echo -n '$(echo true):  ' ; if $(echo true)  ; then echo yes ; else echo no ; fi
echo -n '$(echo false): ' ; if $(echo false) ; then echo yes ; else echo no ; fi
echo -n '$(true):       ' ; if $(true)       ; then echo yes ; else echo no ; fi
echo -n '$(false):      ' ; if $(false)      ; then echo yes ; else echo no ; fi
echo -n '"":            ' ; if ""            ; then echo yes ; else echo no ; fi
echo -n '(nothing):     ' ; if               ; then echo yes ; else echo no ; fi

e aqui está a saída que recebo (Ubuntu 11.04, bash 4.2.8):

true:          yes
false:         no
$(echo true):  yes
$(echo false): no
$(true):       yes
$(false):      no
"":            ./foo.bash: line 9: : command not found
no
./foo.bash: line 10: syntax error near unexpected token `;'
./foo.bash: line 10: `echo -n '(nothing):     ' ; if               ; then echo yes ; else echo no ; fi'

As primeiras quatro linhas se comportam como eu esperava; a$(true) e$(false)inhas são surpreendente

Outra experiência (não mostrada aqui) indica que se o comando entre$( e) produz saída, seu status de saída não afeta o comportamento doif.

Vejo comportamento semelhante (mas, em alguns casos, mensagens de erro diferentes) combash, ksh, zsh, ash edash.

Não vejo nada na documentação do bash ou na especificação POSIX "Shell Command Language" para explicar iss

(Ou talvez esteja perdendo algo óbvio.)

EDIT: À luz da resposta aceita, aqui está outro exemplo do comportamento:

command='' ; if $command ; then echo yes ; else echo no ; fi

ou equivalente

command=   ; if $command ; then echo yes ; else echo no ; fi

questionAnswers(8)

yourAnswerToTheQuestion