Precedência de && vs & no bash e zsh

Precedência de && vs & no bash e zsh

Respondendoessa questãoEu descobri uma diferença muito engraçada (e sutil) entre comportamento em bashe zsh:

Em bash:

romano@RRyS:~$ pwd
/home/romano
romano@RRyS:~$ alias x="cd /bin && ./echo A >/dev/null  &"
romano@RRyS:~$ x
[1] 16611
romano@RRyS:~$ pwd
/home/romano

Como você pode ver, a execução do alias xé realizada em um subshell e portanto o diretório atual não muda.

Não em zsh:

[romano:~] % pwd
/home/romano
[romano:~] % alias x="cd /bin && ./echo A >/dev/null &"
[romano:~] % x
[1] 16744
[1]  + 16744 done       ./echo A >/dev/null                                    
1& [romano:/bin] % pwd
/bin
[romano:/bin] % 

aqui o diretório é alterado.

Parece que &in bashtem uma prioridade diferente de in zsh--- quero dizer, o comando parece ser lido como

(cd /tmp && echo A) & 

em bashe como

cd /tmp && (echo A &) 

em zsh. Isso está correto ou a causa do comportamento diferente é outra?

Responder1

Comportamento diferente e documentado emzshmisc

Uma lista é uma sequência de zero ou mais sublistas, em que cada sublista é terminada por ;, &, &|, &!ou uma nova linha. Este terminador pode opcionalmente ser omitido da última sublista da lista quando a lista aparece como um comando complexo dentro de (...)ou {...}. Quando uma sublista é encerrada por ;ou nova linha, o shell espera que ela termine antes de executar a próxima sublista. Se uma sublista for finalizada por &, &|, ou &!, o shell executa o último pipeline nela em segundo plano e não espera que ele termine (observe a diferença de outros shells que executam toda a sublista em segundo plano). Um pipeline em segundo plano retorna um status zero.

Responder2

Enterrada zshmisc(1)está a seguinte linha:

Se uma sublista for finalizada por um &',&|' ou `&!', o shell executa o último pipeline em segundo plano,

Embora não afirme especificamente que os outros pipelines na sublista são executados no shell atual, isso parece ser o que está implicando, e o comportamento que você observa apoia essa interpretação. Por exemplo:

$ echo $foo $bar

$ foo=3 && bar=5 && sleep 1 &
$ echo $foo $bar
3 5

também suporta a noção de que os dois primeiros pipelines são executados no shell atual e apenas o último pipeline da sublista é realmente executado em segundo plano.

informação relacionada