31

Из этого поста командной строки:

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

Похоже на несколько стандартных вводов, но - если я правильно помню свой курс по программированию Linux - это не может быть. Я думал, что по определению стандартный ввод был одним потоком.

Возможно это имеет отношение к stdin? Может кто-то объяснить это мне; возможно, предоставьте ссылки на документацию.

Бонус: как скрипт будет обрабатывать эти несколько потоков? Если бы кто-то мог предоставить пример Python или Perl, это было бы очень полезно.

3 ответа3

24

Это не множественный стандартный ввод. Это bash'ism, который называется «Замена процесса» http://tldp.org/LDP/abs/html/process-sub.html

Он создает псевдо-файл (/dev/fd/something) для каждой замены. Это довольно полезно. Команду можно читать только как поток, то есть она не может переходить вперед и назад с помощью fseek. Нужно читать это как поток байтов, как канал.

БОНУС Ответ

Вам не нужно делать слишком много, чтобы использовать это. Что касается вашего скрипта, он получает действительное имя файла в командной строке, которое может быть открыто () как любой другой. Как уже говорили другие, вы увидите diff /dev/fd/XX /dev/fd/YY . Если вы выполните stat () для любого из этих псевдофайлов, вы увидите, что это именованный канал, и вам следует использовать семантику канала, а именно: fseek () или ftell (). Если вы делаете тест стат () явно увидеть , если это файл (например , [ -f $1 ] это сломает - это реализуется в виде именованного канала в конце концов.

7

<(...) выполняет подстановку в bash. Выходные данные процесса в скобках отправляются в дополнительный дескриптор файла, выходящий за пределы нормального значения 3, и возвращается имя файла, соответствующее этому дескриптору файла. Таким образом, вывод команды может быть обработан как имя файла для передачи другой команде.

6

Существует один стандартный stdin и один стандартный stdout для каждого процесса. Они обычно подключены к терминалу, но их можно перенаправить отдельно друг от друга.

В этом примере задействованы два процесса wget , каждый из которых получает свои собственные stdin и stdout . Каждый процесс wget записывает в - , что является его стандартным stdout . Затем подстановка процесса в bash <(...) соединяет стандартный stdout процесса с уникальным псевдофайлом, из которого может считывать diff . Обратите внимание, что две подстановки процесса дают два разных псевдофайла! Таким образом, diff видит что-то вроде:

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

где стандартный stdout wget -q -O - URL1 подключен к /dev/fd/XX , а стандартный stdout wget -q -O - URL2 - /dev/fd/YY .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .