Wiele standardowych danych wejściowych? W jaki sposób?

36

Z tego wiersza poleceniafu :

$ diff <(wget -q -O - URL1) <(wget -q -O - URL2)

Wydaje się, że jest to wiele standardowych danych wejściowych, ale --- jeśli dobrze pamiętam mój kurs Linux Porgramming --- to nie może być to. Myślałem, że z definicji standardowe wejście to jeden strumień.

Być może ma to związek ze stdin? Czy ktoś może mi to wyjaśnić; może podać linki do dokumentacji.

Bonus: Jak skrypt poradziłby sobie z tymi wieloma strumieniami? Jeśli ktoś mógłby podać przykład w języku Python lub Perl, byłoby to bardzo pomocne.

Belmin Fernandez
źródło
1
Dobre pytanie. Jeśli nie jesteś świadomy, istnieje strona z pytaniami
Matt Ellen
2
Dokumentacja zastępowania procesów: gnu.org/software/bash/manual/bashref.html#Process-Substitution
glenn jackman
Uwaga: w Bash jest <(…); w procesie Zsh składnia podstawiania to =(…).
Kamil Maciorowski

Odpowiedzi:

27

To nie jest wiele standardowych danych wejściowych. Jest to bashizm, który nazwał „Process Substitution” http://tldp.org/LDP/abs/html/process-sub.html

Tworzy pseudo plik ( /dev/fd/something) dla każdego podstawienia. To całkiem przydatne. Polecenie może być odczytywane tylko jako strumień, co oznacza, że ​​nie może przesuwać się tam iz powrotem z fseek. Musi to odczytać jako strumień bajtów, jak potok.

BONUS Odpowiedź

Nie musisz robić zbyt wiele, aby z tego korzystać. Jeśli chodzi o skrypt, otrzymuje on poprawną nazwę pliku w wierszu poleceń, którą można otworzyć () jak wszystko inne. Jak powiedzieli inni, zobaczysz diff /dev/fd/XX /dev/fd/YY. Jeśli wykonasz stat () na dowolnym z tych pseudoplików, zobaczysz, że jest to nazwany potok i powinieneś traktować go semantyką potoku - mianowicie bez fseek () lub ftell (). Jeśli wykonasz test stat (), aby wyraźnie sprawdzić, czy jest to plik (np. [ -f $1 ]), To się zepsuje - w końcu jest to realizowane jako nazwany potok.

Rich Homolka
źródło
Kolejna dobra referencja do zastępowania procesu bash - wiki.bash-hackers.org/syntax/expansion/proc_subst
studgeek
A jakie jest zalecane użycie tej funkcji? Wesprzeć go, ilekroć Twój program może racjonalnie pracować ze strumieniem zamiast wymagać pliku z losowym dostępem?
masterxilo
7

<(...)dokonuje zamiany w bash. Dane wyjściowe procesu w parens są wysyłane do dodatkowego deskryptora pliku poza normalnym 3, a zwracana jest nazwa pliku odpowiadająca temu deskryptorowi pliku. W ten sposób dane wyjściowe polecenia można traktować jako nazwę pliku, która ma zostać przekazana do innego polecenia.

Ignacio Vazquez-Abrams
źródło
7

Dla każdego procesu jest jeden stdini jeden . Zazwyczaj są one podłączone do terminala, ale można je przekierowywać osobno.stdout

W tym przykładzie wgetzaangażowane są dwa procesy, z których każdy ma swój własny stdini stdout. Każdy wgetproces pisze -, co jest jego stdout. Następnie bashpodstawienie procesu <(...)łączy stdoutproces z unikalnym pseudoplikiem, z którego diffmożna odczytać. Zauważ, że dwie zamiany procesów dają dwa różne pseudopliki! diffWidzi więc coś takiego:

diff /dev/fd/XX /dev/fd/YY

gdzie stdouto wget -q -O - URL1jest podłączony do /dev/fd/XX, i stdoutod wget -q -O - URL2celu /dev/fd/YY.

musiphil
źródło