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

9

Respondendo esta questão Eu descobri um muito engraçado (e sutil ) diferença entre o comportamento em bash e 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 é alterado.

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 o & em bash tem uma prioridade diferente de zsh --- quer dizer, o comando parece ser lido como

(cd /tmp && echo A) & 

em bash e como

cd /tmp && (echo A &) 

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

    
por Rmano 15.10.2014 / 17:41

2 respostas

9

Comportamento diferente e documentado em zshmisc

A list is a sequence of zero or more sublists, in which each sublist is terminated by ;, &, &|, &!, or a newline. This terminator may optionally be omitted from the last sublist in the list when the list appears as a complex command inside (...) or {...}. When a sublist is terminated by ; or newline, the shell waits for it to finish before executing the next sublist. If a sub‐list is terminated by a &, &|, or &!, the shell executes the last pipeline in it in the background, and does not wait for it to finish (note the difference from other shells which execute the whole sublist in the background). A backgrounded pipeline returns a status of zero.

    
por 15.10.2014 / 21:05
3

Enterrada em zshmisc(1) é a seguinte linha:

If a sublist is terminated by a &',&|', or '&!', the shell executes the last pipeline in it in the background,

Embora não especifique especificamente que os outros pipelines na sub-lista são executados no shell atual, isso parece ser o que está implicando, e o comportamento observado suporta 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 somente o último pipeline da sub-lista é executado em segundo plano.

    
por 15.10.2014 / 20:46

Tags