Crear un archivo temporal a partir de una entrada estándar

Crear un archivo temporal a partir de una entrada estándar

Digamos que tengo un flujo de entrada estándar decontenido del archivoy un comando que espera unNombre del archivocomo argumento y quiero ejecutar ese comando en un archivo compuesto por el contenido del archivo del flujo de entrada estándar.

Por ejemplo, en lugar del comando

imageviewer mouse.jpg

Quiero alguna línea mágica magicque haga que esto sea equivalente a

cat mouse.jpg | magic

¿Cómo se vería esto magicen zsho bash?

Preferiblemente me gustaría que se viera como

cat mouse.jpg | submagic | xargs imageviewer

es decir, me gustaría submagiccrear un archivo temporal a partir del flujo de entrada estándar y generar el nombre del archivo creado.

Las líneas magico submagicdeberían ser canalizaciones de shell que utilicen solo comandos bash o zsh, sus funciones integradas, GNU coreutils y similares.


Ésta es toda la cuestión. A continuación se incluyen simplemente aclaraciones y antecedentes porque la gente siguió malinterpretando lo que quise decir.


Vale, pensé que lo había dejado claro, pero parece que no lo hice:en realidadQuiero tener un oleoducto que haga el equivalente a

imageviewer mouse.jpg

esocomienza exactamentecon cat mouse.jpg | …. Es decir, yoen realidaddesearexactamenteuna línea magico submagictal queexactamenteLas tuberías anteriores funcionan. Quise decir mi pregunta literalmente.

Esto significa en particular que las siguientes soluciones sugeridas no funcionarán:

  • comenzando el oleoducto contmpfile = $(mktemp); cat mouse.jpg | …
  • reescribiéndolo comoimageviewer =(cat mouse.jpg)
  • reescribiéndolo comoecho mouse.jpg | xargs imageviewer
  • usando una función o un binario para resolverlo, digamos definiendofunction magic () { … }

Se puede decir que lo que me interesa es si es posible escribir un alias alias magic='…'o alias submagic='…'que una de las canalizaciones anteriores funcione y que la definición de estos alias no contenga nada más que comandos bash o zsh, GNU coreutils y similares. nada escrito por uno mismo.

Otro comentario. Haces tomar imageviewerser feho sxivo algo así.

Fondo. Esta pregunta me surgió cuando intenté abrir varios archivos de imágenes adjuntos a un correo usando mi cliente de correo neomutt. Neomutt ofrece etiquetar archivos adjuntos y luego canalizar el contenido del archivo a una línea de comando que puede escribir. Entonces, aquí solo puedo proporcionar una línea de comando que realiza algo en un flujo de entrada estándar determinado. De ahí surgió la pregunta. Pero no me interesa el problema original, sino sólo esta misma pregunta.

Respuesta1

Al bashmenos, con el uso de unsustitución de procesos:

utility <( some_other_utility )

Esto se presentaría utilitycon unNombre del archivo. Cuando utilityabre el archivo y lo lee, leerá la salida estándar de some_other_utility.


Tu ejemplo:

cat mouse.jpg | submagic | xargs imageviewer

Supongo que esto está destinado a enviar elNombre del archivo mouse.jpga imageviewer, ya que no tiene sentido enviar el contenido de un archivo JPEG a través de xargs.

Eso se podría hacer a través de sólo

echo 'mouse.jpg' | xargs imageviewer

o

xargs imageviewer <<<'mouse.jpg'

en bash.

El envío del contenido de mouse.jpga imageviewerse puede realizar con

cat mouse.jpg | imageviewer /dev/stdin

o, utilizando el proceso de sustitución, con

imageviewer <( cat mouse.jpg )

Usando un archivo temporal:

tmpfile=$(mktemp)
cat mouse.jpg >"$tmpfile"

imageviewer "$tmpfile"

rm "$tmpfile"

Posiblemente,

tmpfile=$(mktemp)
cat mouse.jpg | { cat >"$tmpfile"; echo "$tmpfile"; } | xargs imageviewer
rm "$tmpfile"

Esta canalización se basa en el hecho de que xargsesperaría con la ejecución imageviewerhasta que haya leído el nombre del archivo de la parte media de la canalización. El nombre del archivo no sería generado por el comando central hasta que se hubiera creado el archivo temporal.

Respuesta2

Después de una aclaración submagicen la pregunta, edité la respuesta.

Puede zshcrear un archivo temporal a partir de la salida de un comando con =( ... ). A diferencia de <( ... )lo que puede usar un archivo de dispositivo como /dev/fd...o una canalización con nombre, el formulario =( ... )crea un archivo temporal buscable. Verhttp://zsh.sourceforge.net/Doc/Release/Expansion.html#Process-Substitution

Suponiendo que esto cat mouse.jpges solo un ejemplo para cualquier comando que envíe datos de imagen a la salida estándar, puede usar

imageviewer =(cat mouse.jpg)

Si necesita que el archivo temporal creado por zsh tenga una extensión particular, puede configurar elTMPSUFFIXvariable especial):

(TMPSUFFIX=.jpg; imageviewer =(cat mouse.jpg))

segunda actualización

Si insistes en la sintaxis

cat mouse.jpg | submagic | xargs imageviewer

Sería posible crear un script submagicsimilar a los comandos ya propuestos en la respuesta de Kusalananda.

#! /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"

A diferencia de mecanismos de shell como =( cat mouse.jpg )este, no se eliminan $TMPFILEdespués de ejecutarse imageviewer.

Si puede ejecutar un segundo script después de ejecutarlo imageviewer, podría eliminar el archivo si conoce el nombre.

Guionsubmagic-cleanup

#! /bin/sh

# A fixed name allows a simple script for cleaning up.
TMPFILE=/tmp/submagic.tmp.jpg
rm -f "$TMPFILE"

Entonces podrías correr

cat mouse.jpg | submagic | xargs imageviewer
submagic-cleanup

Respuesta3

Para cumplir con los requisitos exactos de su pregunta, puede hacer:

cat mouse.jpg | { tf=$(mktemp); cat >"$tf"; echo "$tf"; } | xargs imageviewer

información relacionada