
Допустим, у меня есть стандартный входной потоксодержимое файлаи команда, которая ожидаетимя файлав качестве аргумента, и я хочу выполнить эту команду для файла, состоящего из содержимого файла стандартного потока ввода.
Например, вместо команды
imageviewer mouse.jpg
Мне нужна какая-то волшебная линия magic
, которая сделает это эквивалентом
cat mouse.jpg | magic
Как это будет magic
выглядеть в zsh
или bash
?
Предпочтительно, я бы хотел, чтобы это выглядело так
cat mouse.jpg | submagic | xargs imageviewer
то есть я хотел бы submagic
создать временный файл из стандартного потока ввода и вывести имя созданного файла.
Строки magic
или submagic
должны быть конвейерами оболочки, использующими только команды bash или zsh, их встроенные функции, GNU coreutils и тому подобное.
Вот и весь вопрос. Ниже приведены лишь разъяснения и предыстория, поскольку люди продолжали неправильно понимать, что я имел в виду.
Хорошо, я думал, что ясно выразился, но, похоже, я этого не сделал: яДействительнохотите иметь трубопровод, выполняющий эквивалент
imageviewer mouse.jpg
чтоначинается именно такс cat mouse.jpg | …
. То есть, яДействительнохотетьточнолиния magic
или submagic
что-то подобное, чтоточноконвейеры выше работают – я имел в виду свой вопрос буквально.
Это означает, в частности, что следующие предлагаемые решения не подойдут:
- начиная с трубопровода
tmpfile = $(mktemp); cat mouse.jpg | …
- переписывая это как
imageviewer =(cat mouse.jpg)
- переписывая это как
echo mouse.jpg | xargs imageviewer
- используя функцию или двоичный код для ее решения, скажем, путем определения
function magic () { … }
Можно сказать, что меня интересует, возможно ли написать псевдоним alias magic='…'
или alias submagic='…'
сделать так, чтобы один из вышеперечисленных конвейеров работал, а определение этих псевдонимов не содержало ничего, кроме команд bash или zsh, GNU coreutils и тому подобного – ничего самописного.
Еще один комментарий. Вы заставляете взять imageviewer
быть feh
или sxiv
или что-то.
Фон. Этот вопрос возник у меня, когда я попытался открыть несколько файлов изображений, прикрепленных к письму, с помощью моего почтового клиента neomutt
. Neomutt предлагает помечать прикрепленные файлы, а затем передавать содержимое файла в командную строку, которую вы можете ввести. Поэтому здесь я могу только дать командную строку, которая выполняет что-то в заданном стандартном потоке ввода. Вот откуда возник вопрос. Но меня интересует не исходная проблема, а только этот самый вопрос.
решение1
По bash
крайней мере, с использованиемзамена процесса:
utility <( some_other_utility )
Это будет представлять utility
собойимя файла. При utility
открытии файла и чтении из него будет прочитан стандартный вывод some_other_utility
.
Ваш пример:
cat mouse.jpg | submagic | xargs imageviewer
Я предполагаю, что это предназначено для отправкиимя файла mouse.jpg
в imageviewer
, так как не имеет смысла отправлять содержимое файла JPEG через xargs
.
Это можно сделать просто
echo 'mouse.jpg' | xargs imageviewer
или
xargs imageviewer <<<'mouse.jpg'
в bash
.
Отправка содержимого mouse.jpg
в imageviewer
может быть выполнена с помощью
cat mouse.jpg | imageviewer /dev/stdin
или, используя замену процесса, с
imageviewer <( cat mouse.jpg )
Использование временного файла:
tmpfile=$(mktemp)
cat mouse.jpg >"$tmpfile"
imageviewer "$tmpfile"
rm "$tmpfile"
Возможно,
tmpfile=$(mktemp)
cat mouse.jpg | { cat >"$tmpfile"; echo "$tmpfile"; } | xargs imageviewer
rm "$tmpfile"
Этот конвейер полагается на тот факт, что xargs
он будет ждать выполнения imageviewer
, пока не прочитает имя файла из средней части конвейера. Имя файла не будет выводиться средней командой, пока не будет создан временный файл.
решение2
После уточнения submagic
вопроса я отредактировал ответ.
В zsh
вы можете создать временный файл из вывода команды с =( ... )
. В отличие от <( ... )
, который может использовать файл устройства, например /dev/fd...
, или именованный канал, форма =( ... )
создает временный файл с возможностью поиска. Смотритеhttp://zsh.sourceforge.net/Doc/Release/Expansion.html#Process-Substitution
Предполагая, что cat mouse.jpg
это всего лишь пример для любой команды, которая отправляет данные изображения на стандартный вывод, вы можете использовать
imageviewer =(cat mouse.jpg)
Если вам необходимо, чтобы временный файл, созданный zsh, имел определенное расширение, вы можете задатьTMPSUFFIX
специальная переменная):
(TMPSUFFIX=.jpg; imageviewer =(cat mouse.jpg))
второе обновление
Если вы настаиваете на синтаксисе
cat mouse.jpg | submagic | xargs imageviewer
можно было бы создать сценарий, submagic
аналогичный командам, уже предложенным в ответе Кусалананды.
#! /bin/sh
# A fixed name allows multiple runs without creating lots of files and
# allows a simple script to remove the file afterwards.
TMPFILE=/tmp/submagic.tmp.jpg
rm -f "$TMPFILE" && cat > "$TMPFILE" && echo "$TMPFILE"
В отличие от оболочек подобные механизмы =( cat mouse.jpg )
не удаляются $TMPFILE
после запуска imageviewer
.
Если после этого запустить второй скрипт, imageviewer
он может удалить файл, если знает его имя.
Сценарийsubmagic-cleanup
#! /bin/sh
# A fixed name allows a simple script for cleaning up.
TMPFILE=/tmp/submagic.tmp.jpg
rm -f "$TMPFILE"
Тогда ты мог бы бежать
cat mouse.jpg | submagic | xargs imageviewer
submagic-cleanup
решение3
Чтобы точно соответствовать требованиям вашего вопроса, вы можете сделать следующее:
cat mouse.jpg | { tf=$(mktemp); cat >"$tf"; echo "$tf"; } | xargs imageviewer