Jednowierszowy z 2 plikami tmp (nie tym, czego chcesz) byłby:
foo | bar > file1.txt && baz | quux > file2.txt && diff file1.txt file2.txt
W przypadku basha możesz jednak spróbować:
diff <(foo | bar) <(baz | quux)
foo | bar | diff - <(baz | quux) # or only use process substitution once
Druga wersja będzie wyraźniej przypominać ci, które wejście było które, pokazując
-- /dev/stdin
vs. ++ /dev/fd/63
lub coś, zamiast dwóch ponumerowanych fds.
Nawet nazwany potok nie pojawi się w systemie plików, przynajmniej w systemach operacyjnych, w których bash może zaimplementować podstawianie procesów przy użyciu nazw plików, takich jak /dev/fd/63
uzyskanie nazwy pliku, którą polecenie może otworzyć i odczytać, aby faktycznie czytać z już otwartego deskryptora pliku ustawionego przez bash up przed wykonaniem polecenia. (tj. bash używa pipe(2)
przed rozwidleniem, a następnie dup2
przekierowuje z wyjścia quux
do deskryptora pliku wejściowego dla diff
, na fd 63.)
W systemie bez "magicznych" /dev/fd
lub /proc/self/fd
, bash może używać nazwanych potoków do implementacji podstawiania procesów, ale przynajmniej sam zarządzałby nimi, w przeciwieństwie do plików tymczasowych, a twoje dane nie zostałyby zapisane w systemie plików.
Możesz sprawdzić, jak bash implementuje podstawianie za pomocą, echo <(true)
aby wypisać nazwę pliku zamiast czytać z niego. Drukuje /dev/fd/63
na typowym systemie Linux. Aby uzyskać więcej informacji na temat dokładnie tego, jakich wywołań systemowych używa bash, to polecenie w systemie Linux będzie śledzić wywołania systemowe plików i deskryptorów plików
strace -f -efile,desc,clone,execve bash -c '/bin/true | diff -u - <(/bin/true)'
Bez basha możesz stworzyć nazwaną potokę . Służy -
do mówienia, diff
aby odczytać jedno wejście ze STDIN i użyj nazwanego potoku jako drugiego:
mkfifo file1_pipe.txt
foo|bar > file1_pipe.txt && baz | quux | diff file1_pipe.txt - && rm file1_pipe.txt
Zauważ, że możesz przesłać tylko jedno wyjście do wielu wejść za pomocą polecenia tee:
ls *.txt | tee /dev/tty txtlist.txt
Powyższe polecenie wyświetla wyjście ls * .txt na terminal i wyprowadza je do pliku tekstowego txtlist.txt.
Ale dzięki podstawianiu procesów możesz użyć tee
do wprowadzenia tych samych danych do wielu potoków:
cat *.txt | tee >(foo | bar > result1.txt) >(baz | quux > result2.txt) | foobar
mkfifo a; cmd >a& cmd2|diff a -; rm a