Vorrang von && gegenüber & in Bash und Zsh

Vorrang von && gegenüber & in Bash und Zsh

Antwortendiese FrageIch habe einen sehr lustigen (und subtilen) Unterschied zwischen dem Verhalten in bashund entdeckt 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

Wie Sie sehen, xwird die Ausführung von Alias ​​in einer Subshell durchgeführt und daher ändert sich das aktuelle Verzeichnis nicht.

Nicht 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] % 

hier wird das Verzeichnis gewechselt.

Es scheint, dass &in basheine andere Priorität hat als in zsh--- Ich meine, der Befehl wird anscheinend gelesen als

(cd /tmp && echo A) & 

in bashund als

cd /tmp && (echo A &) 

in zsh. Ist das richtig oder liegt die Ursache für das abweichende Verhalten woanders?

Antwort1

Unterschiedliches, dokumentiertes Verhalten inzshmisc

Eine Liste ist eine Folge von null oder mehr Unterlisten, in denen jede Unterliste durch ;, &, &|, &!, oder einen Zeilenumbruch abgeschlossen wird. Dieser Abschluss kann optional aus der letzten Unterliste in der Liste weggelassen werden, wenn die Liste als komplexer Befehl innerhalb von (...)oder erscheint {...}. Wenn eine Unterliste durch ;oder einen Zeilenumbruch abgeschlossen wird, wartet die Shell, bis sie beendet ist, bevor sie die nächste Unterliste ausführt. Wenn eine Unterliste durch &, &|, oder abgeschlossen wird &!, führt die Shell die letzte Pipeline darin im Hintergrund aus und wartet nicht, bis sie beendet ist (beachten Sie den Unterschied zu anderen Shells, die die ganze Unterliste im Hintergrund ausführen). Eine im Hintergrund ausgeführte Pipeline gibt den Status 0 zurück.

Antwort2

Darin vergraben zshmisc(1)ist die folgende Zeile:

Wenn eine Unterliste durch ein &|' oder `&!' beendet wird &',, führt die Shell die letzte darin enthaltene Pipeline im Hintergrund aus.

Obwohl nicht ausdrücklich angegeben ist, dass die anderen Pipelines in der Unterliste in der aktuellen Shell ausgeführt werden, scheint dies zu implizieren, und das von Ihnen beobachtete Verhalten unterstützt diese Interpretation. Beispiel:

$ echo $foo $bar

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

unterstützt auch die Vorstellung, dass die ersten beiden Pipelines in der aktuellen Shell ausgeführt werden und nur die letzte Pipeline der Unterliste tatsächlich im Hintergrund ausgeführt wird.

verwandte Informationen