Die <(list)Syntax wird von bashund unterstützt zsh. Es bietet eine Möglichkeit, die Ausgabe eines Befehls ( list) an einen anderen Befehl zu übergeben, wenn die Verwendung einer Pipe ( |) nicht möglich ist. Zum Beispiel, wenn ein Befehl nur keine Eingabe von unterstützt STDINoder Sie die Ausgabe mehrerer Befehle benötigen:
diff <(ls dirA)<(ls dirB)
<(list)Verbindet die Ausgabe von listmit einer Datei in /dev/fd, wenn dies vom System unterstützt wird. Andernfalls wird eine Named Pipe (FIFO) verwendet (dies hängt auch von der Unterstützung durch das System ab. In keinem Handbuch wird angegeben, was passiert, wenn beide Mechanismen nicht unterstützt werden. Vermutlich wird dies abgebrochen ein Fehler). Der Name der Datei wird dann in der Befehlszeile als Argument übergeben.
zshunterstützt zusätzlich =(list)als möglicher ersatz für <(list). Bei =(list)einer temporären Datei wird anstelle von Datei /dev/fdein FIFO verwendet. Es kann als Ersatz für <(list)den Fall verwendet werden, dass das Programm in der Ausgabe suchen muss.
Laut ZSH-Handbuch kann es auch andere Probleme mit der Funktionsweise geben <(list):
Das =Formular ist nützlich, da sowohl /dev/fddie Named-Pipe-Implementierung als auch <(...)die Named- Pipe-Implementierung Nachteile aufweisen. Im ersteren Fall schließen einige Programme möglicherweise den betreffenden Dateideskriptor automatisch, bevor sie die Datei in der Befehlszeile untersuchen, insbesondere wenn dies aus Sicherheitsgründen erforderlich ist, z. B. wenn das Programm setuid ausführt. Wenn im zweiten Fall das Programm die Datei nicht öffnet, wird die Subshell, die versucht, aus der Pipe zu lesen oder in die Pipe zu schreiben, für immer blockiert (in einer typischen Implementierung haben unterschiedliche Betriebssysteme möglicherweise ein unterschiedliches Verhalten) und muss explizit beendet werden . In beiden Fällen stellt die Shell die Informationen tatsächlich über eine Pipe bereit, sodass Programme, die erwarten, in lseek(2)der Datei nach Informationen zu suchen (siehe Manpage ), nicht funktionieren.
Dies half mir herauszufinden, warum MacOS pfctl -f <(echo "pf rules")einen schlechten Dateideskriptor sagte. Die Verwendung von zsh und = (echo "pf rules") funktioniert stattdessen.
JohnnyB
9
Beachten Sie, dass dies eine bash Antwort ist, nicht zsh.
Es gibt Fälle in Bash, in denen Sie keine Pipes verwenden können:
some_command | some_other_command
Da Pipes Unterschalen für jede Komponente der Pipeline einführen, verschwinden beim Verlassen der Unterschalen alle Nebenwirkungen, auf die Sie sich verlassen. Zum Beispiel dieses erfundene Beispiel:
= (cmdlist) in zsh hat fast den gleichen Effekt wie <(cmdlist) in bash, erstellt (und löscht, wenn es fertig ist) jedoch eine temporäre Datei mit der Ausgabe von cmdlist für die Umleitung. Dies ist gut, wenn die Suche möglicherweise im Programm erfolgt. <(cmdlist) ist auch bei zsh bekannt.
pfctl -f <(echo "pf rules")
einen schlechten Dateideskriptor sagte. Die Verwendung von zsh und = (echo "pf rules") funktioniert stattdessen.Beachten Sie, dass dies eine bash Antwort ist, nicht zsh.
Es gibt Fälle in Bash, in denen Sie keine Pipes verwenden können:
Da Pipes Unterschalen für jede Komponente der Pipeline einführen, verschwinden beim Verlassen der Unterschalen alle Nebenwirkungen, auf die Sie sich verlassen. Zum Beispiel dieses erfundene Beispiel:
zeigt eine leere Zeile an, da die
$count
Variable in der aktuellen Shell nicht vorhanden ist.Mit einer Bash- Prozessersetzung können Sie dieses Rätsel umgehen, indem Sie aus der Ausgabe von "some_command" wie aus einer Datei lesen
(1) ist eine normale Eingabeumleitung. (2) ist der Beginn der
<()
Prozesssubstitutionssyntax.quelle