Diutamakan dari && vs & dalam bash dan zsh

9

Menjawab pertanyaan ini saya menemukan perbedaan yang sangat lucu (dan halus) antara perilaku dalam bashdan zsh:

Dalam 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

Seperti yang Anda lihat, eksekusi alias xdilakukan dalam subkulit dan direktori saat ini tidak berubah.

Tidak di 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] % 

di sini direktori diubah.

Tampaknya &di bashmemiliki prioritas yang berbeda dari di zsh--- Maksud saya, perintah itu tampaknya dibaca sebagai

(cd /tmp && echo A) & 

di bashdan sebagai

cd /tmp && (echo A &) 

di zsh. Apakah ini benar atau penyebab dari perilaku yang berbeda adalah penyebab lainnya?

Rmano
sumber

Jawaban:

9

Berbeda, perilaku yang didokumentasikan di zshmisc

Daftar adalah urutan nol atau lebih sublists, di mana setiap sublist diakhiri oleh ;, &, &|, &!, atau baris baru. Terminator ini secara opsional dapat dihilangkan dari sublist terakhir dalam daftar ketika daftar muncul sebagai perintah kompleks di dalam (...)atau {...}. Ketika sublist diakhiri oleh ;atau baris baru, shell menunggu sampai selesai sebelum menjalankan sublist berikutnya. Jika sublist diakhiri oleh &, &|atau &!, shell mengeksekusi pipa terakhir di dalam latar belakang, dan tidak menunggu sampai selesai (perhatikan perbedaan dari kerang lain yang mengeksekusi seluruh sublist di latar belakang). Pipa latar belakang mengembalikan status nol.

llua
sumber
3

Dimakamkan di zshmisc(1)adalah baris berikut:

Jika sublist diakhiri oleh a &',& | ', atau `&!', Shell mengeksekusi pipa terakhir di dalamnya di latar belakang,

Meskipun tidak secara khusus menyatakan bahwa saluran pipa lain dalam sublist dieksekusi di shell saat ini, tampaknya memang seperti apa yang tersirat, dan perilaku yang Anda amati mendukung interpretasi itu. Sebagai contoh:

$ echo $foo $bar

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

juga mendukung gagasan bahwa dua pipa pertama dijalankan dalam shell saat ini, dan hanya pipa terakhir dari sublist yang benar-benar dieksekusi di latar belakang.

chepner
sumber