Создание временного файла из стандартного ввода

Создание временного файла из стандартного ввода

Допустим, у меня есть стандартный входной потоксодержимое файлаи команда, которая ожидаетимя файлав качестве аргумента, и я хочу выполнить эту команду для файла, состоящего из содержимого файла стандартного потока ввода.

Например, вместо команды

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

Связанный контент