Antwortendiese FrageIch habe einen sehr lustigen (und subtilen) Unterschied zwischen dem Verhalten in bash
und 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, x
wird 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 bash
eine andere Priorität hat als in zsh
--- Ich meine, der Befehl wird anscheinend gelesen als
(cd /tmp && echo A) &
in bash
und 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.