Eine einzeilige mit 2 tmp-Dateien (nicht das, was Sie wollen) würde:
foo | bar > file1.txt && baz | quux > file2.txt && diff file1.txt file2.txt
Mit bash, könnte man allerdings versuchen:
diff <(foo | bar) <(baz | quux)
foo | bar | diff - <(baz | quux) # or only use process substitution once
Die zweite Version wird mehr deutlich daran erinnern, welche Eingabe was war, indem
-- /dev/stdin
vs ++ /dev/fd/63
oder etwas angezeigt wird, anstelle von zwei nummerierten fds.
Nicht einmal ein Named Pipe wird im Dateisystem erscheinen, zumindest auf OSes wo bash kann wie /dev/fd/63
mithilfe von Dateinamen Prozess Substitution implementieren, um einen Dateinamen zu erhalten, dass der Befehl öffnen und liest aus, um tatsächlich von einem lesen Bereits geöffneter Dateideskriptor, den bash vor dem Ausführen des Befehls eingerichtet hat. (Für diff
auf fd 63. dh bash verwendet pipe(2)
vor Gabel und dann dup2
von dem Ausgang der quux
an einen Eingang Dateideskriptor zu umleiten)
ohne „magische“ /dev/fd
oder /proc/self/fd
Auf einem System schlag verwenden könnte benannte Pipes, um die Prozesssubstitution zu implementieren, aber im Gegensatz zu temporären Dateien würden sie sie zumindest selbst verwalten und Ihre Daten würden nicht in das Dateisystem geschrieben werden.
Sie können überprüfen, wie bash die Prozesssubstitution mit echo <(true)
implementiert, um den Dateinamen zu drucken, anstatt von ihm zu lesen. Es druckt /dev/fd/63
auf einem typischen Linux-System. Oder für weitere Details über genau das, was Systemaufrufe bash verwendet, dieser Befehl auf einem Linux-System-Trace-Datei und Datei-Descriptor System ruft
strace -f -efile,desc,clone,execve bash -c '/bin/true | diff -u - <(/bin/true)'
Ohne bash, könnten Sie eine Named Pipe machen.Verwenden Sie -
diff
zu sagen, eine Eingabe von STDIN zu lesen, und verwenden Sie die Named Pipe als die anderen:
mkfifo file1_pipe.txt
foo|bar > file1_pipe.txt && baz | quux | diff file1_pipe.txt - && rm file1_pipe.txt
Hinweis, dass Sie nur Rohr einen Ausgang-mehr Eingänge mit dem Befehl tee :
ls *.txt | tee /dev/tty txtlist.txt
der obige Befehl zeigt die Ausgabe des ls * .txt an das Terminal und gibt es in der Textdatei txtlist.txt.
Aber mit Prozess Substitution, können Sie tee
verwenden die gleichen Daten in mehrere Pipelines zu füttern:
cat *.txt | tee >(foo | bar > result1.txt) >(baz | quux > result2.txt) | foobar
sogar ohne bash, können Sie temporäre fifo 's mfifo a verwenden; cmd> a & cmd2 | diff a -; rm a' – unhammer
Sie können eine reguläre Pipe für einen der Argumente verwenden: 'pipeline1 | diff -u - <(pipeline2) '. Dann wird die Ausgabe deutlicher Sie daran erinnern, welche Eingabe war, indem Sie '_/dev/stdin' vs.' ++/dev/fd/67' oder etwas anstelle von zwei nummerierten fds zeigen. –
Prozesssubstitution ('foo <(pipe)') ändert das Dateisystem nicht. ** Die Pfeife ist * anonym *; Es hat keinen Namen im Dateisystem **. Die Shell verwendet den Systemaufruf "pipe", um sie zu erstellen, nicht "mkfifo". Verwenden Sie 'strace -f -datei, desc, clone, execve bash -c '/ bin/true | diff -u - <(/ bin/true) ', um Datei- und Dateideskriptor-Systemaufrufe zu verfolgen, wenn Sie selbst sehen möchten.Unter Linux ist '/ dev/fd/63' Teil des'/proc' virtuellen Dateisystems; Es enthält automatisch Einträge für jeden Dateideskriptor, und es ist keine Kopie des Inhalts. Sie können das also nicht als "temporäre Datei" bezeichnen, es sei denn, 'foo 3