В bash
, я могу использовать Process Замещение и лакомство выход процесса , как если бы это был файл , сохраненный на диске:
$ echo <(ls)
/dev/fd/63
$ ls -lAhF <(ls)
lr-x------ 1 root root 64 Sep 17 12:55 /dev/fd/63 -> pipe:[1652825]
к сожалению, замена процесса не поддерживается в dash
.
Какой будет лучший способ подражать Process Substitution
в тире?
Я не хочу сохранять вывод как временный файл где-то ( /tmp/
), а затем должен удалить его. Есть ли альтернативный способ?
process-substitution
dash
Мартин Вегтер
источник
источник
bash
на свое устройство?/dev/fd
и использованияxz -cd <file>
вместоcat <file> | xz -d
) может бытьxz -cd "$1" | { xz -cd "$2" | { diff /dev/fd/3 /dev/fd/4; } 3<&0; } 4<&0
.Ответы:
Вопрос в текущем уведомлении о вознаграждении:
кажется, здесь есть ответ .
Как показано в ответе Жиля , общая идея состоит в том, чтобы отправлять выходные данные команд «продюсера» в файлы 1 новых устройств на разных этапах конвейера, делая их доступными для команд «потребителя», которые могут принимать имена файлов в качестве аргументов ( при условии, что ваша система дает вам доступ к файловым дескрипторам как
/dev/fd/X
).Самый простой способ достичь того, что вы ищете, это:
(Использование
file1.xz
вместо"$1"
удобочитаемости, аxz -cd
неcat ... | xz -d
потому, что достаточно одной команды).Выход первой команды «продюсер»
xz -cd file1.xz
передается в составную команду ({...}
); но вместо немедленного использования в качестве стандартного ввода следующей команды, он дублируется в дескрипторе файла3
и, таким образом, становится доступным для всего внутри составной команды as/dev/fd/3
. Выходные данные второй команды «продюсер»xz -cd file2.xz
, которая не использует ни своего стандартного ввода, ни чего-либо из файлового дескриптора3
, затем передаются в команду «потребителя»diff
, которая считывает из своего стандартного ввода и из/dev/fd/3
.Может быть добавлено дублирование трубопровода и дескриптора файла, чтобы обеспечить файлы устройства для стольких команд «производителя», сколько необходимо, например:
Хотя это может быть неуместно в контексте вашего конкретного вопроса, стоит отметить, что:
cmd1 <(cmd2) <(cmd3)
,cmd2 | { cmd3 | { cmd1 /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0
И( cmd2 | ( cmd3 | ( cmd1 /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 )
имеют различные потенциальные эффекты на начальной среде выполнения.Вопреки тому, что происходит в
cmd1 <(cmd2) <(cmd3)
,cmd3
иcmd1
вcmd2 | { cmd3 | { cmd1 /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0
не сможет прочитать какие-либо входные данные от пользователя. Это потребует дополнительных файловых дескрипторов. Например, чтобы соответствоватьвам понадобится что-то вроде
1 Более подробную информацию о них можно найти в U & L, например, в Understanding / dev и его подкаталогах и файлах .
источник
Вы можете воспроизвести то, что делает оболочка под капотом, выполнив сантехнику вручную. Если в вашей системе есть записи, вы можете использовать перестановку дескриптора файла: вы можете перевести
/dev/fd/NNN
в
Я показал более сложный пример, чтобы проиллюстрировать несколько входов и выходов. Если вам не нужно читать из стандартного ввода, и единственная причина, по которой вы используете подстановку процессов, заключается в том, что команде требуется явное имя файла, вы можете просто использовать
/dev/stdin
:Без , вам нужно использовать именованный канал . Именованный канал - это запись каталога, поэтому вам нужно где-то создать временный файл, но этот файл - просто имя, он не содержит никаких данных.
/dev/fd/NNN
источник
</dev/fd/8 >/dev/fd/9
не эквивалентны в<&8 >&9
Linux и их следует избегать.diff <(cat "$2" | xz -d) <(cat "$1" | xz -d)
?Я думаю, что именованные каналы проще перенимать, чем перенаправления, поэтому в простейших терминах:
p1
иp2
являются временными именованными каналами, они могут быть названы как угодно.Было бы разумнее создать каналы
/tmp
, например, в каталоге, как показывает ответ Жиля , и заметьте, что вамcat
здесь не нужно , поэтому:(Вероятно, вы могли бы обойтись и без кавычек, поскольку
mktemp
, скорее всего, создадите «красивые» имена файлов.)У конвейерного решения есть предостережение о том, что если основная команда (
diff
) умирает до прочтения всех входных данных, фоновые процессы можно оставить в подвешенном состоянии.источник
Как насчет:
источник