Precedencia de && vs & en bash y zsh

Precedencia de && vs & en bash y zsh

Respondiendoesta preguntaDescubrí una diferencia muy divertida (y sutil) entre el comportamiento en bashy zsh:

En 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 puede ver, la ejecución del alias xse lleva a cabo en un subshell y, por lo tanto, el directorio actual no cambia.

No en 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] % 

aquí se cambia el directorio.

Parece que &in bashtiene una prioridad diferente que in zsh--- quiero decir, el comando parece leerse como

(cd /tmp && echo A) & 

en bashy como

cd /tmp && (echo A &) 

en zsh. ¿Es esto correcto o la causa del diferente comportamiento es otra?

Respuesta1

Comportamiento diferente y documentado enzshmisc

Una lista es una secuencia de cero o más sublistas, en la que cada sublista termina con ;, &, &|, &!o una nueva línea. Opcionalmente, este terminador se puede omitir de la última sublista de la lista cuando la lista aparece como un comando complejo dentro de (...)o {...}. Cuando una sublista termina con ;una nueva línea, el shell espera a que termine antes de ejecutar la siguiente sublista. Si una sublista termina con &, &|o &!, el shell ejecuta la última canalización en segundo plano y no espera a que finalice (tenga en cuenta la diferencia con otros shells que ejecutan la sublista completa en segundo plano). Una canalización en segundo plano devuelve un estado de cero.

Respuesta2

Enterrada zshmisc(1)está la siguiente línea:

Si una sublista termina con un &',&|' o `&!', el shell ejecuta la última canalización en segundo plano,

Si bien no indica específicamente que las otras canalizaciones en la sublista se ejecutan en el shell actual, eso parece ser lo que implica, y el comportamiento que observa respalda esa interpretación. Por ejemplo:

$ echo $foo $bar

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

también admite la noción de que las dos primeras canalizaciones se ejecutan en el shell actual, y solo la última canalización de la sublista realmente se ejecuta en segundo plano.

información relacionada