In bash
kann ich Process Substitution verwenden und die Ausgabe eines Prozesses so behandeln, als wäre es eine auf der Festplatte gespeicherte Datei:
$ echo <(ls)
/dev/fd/63
$ ls -lAhF <(ls)
lr-x------ 1 root root 64 Sep 17 12:55 /dev/fd/63 -> pipe:[1652825]
Leider wird die Prozessersetzung in nicht unterstützt dash
.
Was wäre der beste Weg, um Process Substitution
im Bindestrich zu emulieren ?
Ich möchte die Ausgabe nicht als temporäre Datei speichern ( /tmp/
) und muss sie dann löschen. Gibt es einen alternativen Weg?
process-substitution
dash
Martin Vegter
quelle
quelle
bash
auf Ihrem Gerät zu installieren ?/dev/fd
undxz -cd <file>
stattdessen verwendet wirdcat <file> | xz -d
) lautenxz -cd "$1" | { xz -cd "$2" | { diff /dev/fd/3 /dev/fd/4; } 3<&0; } 4<&0
.Antworten:
Die Frage im aktuellen Kopfgeldbescheid:
scheint hier eine antwort zu haben .
Wie in Gilles 'Antwort gezeigt , besteht die allgemeine Idee darin, die Ausgabe von "Producer" -Befehlen in verschiedenen Phasen einer Pipeline an neue Gerätedateien 1 zu senden und sie "Consumer" -Befehlen zur Verfügung zu stellen, die möglicherweise Dateinamen als Argumente verwenden ( vorausgesetzt, Ihr System gibt Ihnen Zugriff auf die Dateideskriptoren als
/dev/fd/X
).Der einfachste Weg, um das zu erreichen, wonach Sie suchen, ist wahrscheinlich:
(Verwenden
file1.xz
statt"$1"
für die Lesbarkeit undxz -cd
stattcat ... | xz -d
weil ein einziger Befehl ausreicht).Die Ausgabe des ersten "Producer" -Befehls
xz -cd file1.xz
wird an einen zusammengesetzten Befehl ({...}
) weitergeleitet. Anstatt jedoch sofort als Standardeingabe für den nächsten Befehl verwendet zu werden, wird sie in den Dateideskriptor dupliziert3
und somit für alle Elemente des zusammengesetzten Befehls als verfügbar gemacht/dev/fd/3
. Die Ausgabe des zweiten "Producer" -Befehls,xz -cd file2.xz
der weder seine Standardeingabe noch irgendetwas aus dem Dateideskriptor verbraucht3
, wird dann an den "Consumer" -Befehl weitergeleitetdiff
, der aus seiner Standardeingabe und aus liest/dev/fd/3
.Piping und Duplikation von Dateideskriptoren können hinzugefügt werden, um Gerätedateien für beliebig viele "Producer" -Befehle bereitzustellen, z.
Während es im Kontext Ihrer spezifischen Frage irrelevant sein mag, ist es erwähnenswert, dass:
cmd1 <(cmd2) <(cmd3)
,cmd2 | { cmd3 | { cmd1 /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0
Und( cmd2 | ( cmd3 | ( cmd1 /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 )
haben verschiedene mögliche Auswirkungen auf die anfängliche Ausführungsumgebung.Im Gegensatz zu dem, was in passiert
cmd1 <(cmd2) <(cmd3)
,cmd3
undcmd1
incmd2 | { cmd3 | { cmd1 /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0
wird keine Eingaben des Benutzers lesen können. Dafür sind weitere Dateideskriptoren erforderlich. Zum Beispiel, um zusammenzupassendu wirst sowas brauchen
1 Weitere Informationen hierzu finden Sie in U & L, z. B. in Understanding / dev und seinen Unterverzeichnissen und Dateien .
quelle
Sie können reproduzieren, was die Schale unter der Haube tut, indem Sie die Installation manuell ausführen. Wenn Ihr System Einträge enthält, können Sie die Dateideskriptormischung verwenden: Sie können übersetzen
/dev/fd/NNN
zu
Ich habe ein komplexeres Beispiel gezeigt, um mehrere Ein- und Ausgänge zu veranschaulichen. Wenn Sie nicht aus der Standardeingabe lesen müssen und die Prozessersetzung nur deshalb verwenden, weil für den Befehl ein expliziter Dateiname erforderlich ist, können Sie einfach Folgendes verwenden
/dev/stdin
:Ohne müssen Sie eine Named Pipe verwenden . Eine Named Pipe ist ein Verzeichniseintrag. Sie müssen also irgendwo eine temporäre Datei erstellen, aber diese Datei ist nur ein Name, sie enthält keine Daten.
/dev/fd/NNN
quelle
</dev/fd/8 >/dev/fd/9
sind nicht gleichbedeutend mit<&8 >&9
unter Linux und sollten dort vermieden werden.diff <(cat "$2" | xz -d) <(cat "$1" | xz -d)
?Ich denke, Named Pipes sind einfacher zu verstehen als Umleitungen. Einfach ausgedrückt:
p1
undp2
sind temporäre Named Pipes, sie könnten alles genannt werden.Es wäre klüger, die Rohre in erstellen
/tmp
, zB in einem Verzeichnis wie Gilles' Antwort zeigt, und beachten Sie, dass Sie nicht brauchencat
hier, so:(Sie könnten wahrscheinlich auch ohne die Anführungszeichen davonkommen, da
mktemp
wahrscheinlich "nette" Dateinamen erstellt werden.)Die Pipe-Lösung hat den Vorbehalt, dass
diff
die Hintergrundprozesse hängen bleiben können , wenn der Hauptbefehl ( ) vor dem Lesen aller Eingaben abbricht.quelle
Wie wäre es mit:
quelle