Precedenza di && vs & in bash e zsh


9

Rispondendo a questa domanda ho scoperto una differenza molto divertente (e sottile) tra comportamento in bashe zsh:

In 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

Come puoi vedere, l'esecuzione dell'alias xviene eseguita in una subshell e quindi la directory corrente non cambia.

Non in 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] % 

qui la directory è cambiata.

Sembra che &in bashabbia una priorità diversa da in zsh--- Voglio dire, il comando sembra essere letto come

(cd /tmp && echo A) & 

in bashe come

cd /tmp && (echo A &) 

in zsh. È corretto o la causa del diverso comportamento è un'altra?

Risposte:


9

Comportamento diverso e documentato in zshmisc

Una lista è una sequenza di zero o più sottoliste, in cui ogni sottoelenco viene terminato da ;, &, &|, &!, o una nuova riga. Questo terminatore può facoltativamente essere omesso dall'ultimo elenco secondario nell'elenco quando l'elenco appare come un comando complesso all'interno (...)o {...}. Quando un elenco secondario viene terminato da ;o newline, la shell attende che termini prima di eseguire il successivo elenco secondario. Se un elenco secondario termina con un &, &|o &!, la shell esegue l'ultimo pipeline in in background, e non aspetta che finisca (si noti la differenza con altre shell che eseguono l'intero sottolista in background). Una pipeline in background restituisce uno stato pari a zero.


3

Sepolto in zshmisc(1)è la seguente riga:

Se un elenco secondario termina con un &',& | ', o `&!', La shell esegue l'ultima pipeline al suo interno in background,

Sebbene non specifichi specificamente che le altre pipeline nell'elenco secondario siano eseguite nella shell corrente, sembra che ciò sia implicito e il comportamento che osservi supporta tale interpretazione. Per esempio:

$ echo $foo $bar

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

supporta anche l'idea secondo cui le prime due pipeline vengono eseguite nella shell corrente e solo l'ultima pipeline dell'elenco secondario viene effettivamente eseguita in background.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.