Na verdade, é mais o seguinte:
$ 'nonsense'
bash: nonsense: command not found
$ echo "$?"
127
Isso é surpreendente aqui.
Pedimos que bash
execute o comando que resulta do operador split + glob no stdout de nonsense
. Como nonsense
não produz saída, ele não executa nenhum comando, portanto você pode achar que o status de saída deve ser 0.
Mas, na verdade, quando uma linha de comando simples não possui argumento, apenas atribuição ou redirecionamento, o status de saída é o da última substituição de comando em atribuição e palavras normais (não em alvos de redirecionamento) executadas (embora a falha nos redirecionamentos seja também afeta o status de saída).
Isso é especialmente útil com atribuições.
Em:
output=$(grep pattern file)
status=$?
Você pode obter o status de saída e saída de grep
, o que não seria possível se $?
fosse o status de saída desse não-comando.
Em:
output=$(cmd1) cmd2
É aí que existem palavras de atribuição e palavras de argumento, o status de saída de cmd1
é ignorado. $?
conterá o status de saída de cmd2
.
E também $output
será definido apenas para cmd2
. Exceção para isso é quando cmd2
é um especial embutido.
eval
é um especial .
$ a=0; a=1 eval; echo "$a"
1
Em bash
e nas mais modernas caixas POSIX.
a='exit 5' eval; echo "$?"
ou
eval 'exit 5'; echo "$?"
A saída seria 0, pois é o resultado da execução de eval
sem argumento. Mas esse não era o caso no shell Bourne ou no ksh88, onde para construtores especiais você obteria o status de saída de exit 5
.
Nestas conchas, você também encontrará:
$ a='exit 3' set x; echo "$?"
3
Como set
é outro especial incorporado.
.
é outro especial incorporado. No shell Bourne e no ksh88:
$ . /some/file 'exit 4'; echo "$?"
4
(contanto que /some/file
não execute nenhum comando)