
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 magic
que haga que esto sea equivalente a
cat mouse.jpg | magic
¿Cómo se vería esto magic
en zsh
o bash
?
Preferiblemente me gustaría que se viera como
cat mouse.jpg | submagic | xargs imageviewer
es decir, me gustaría submagic
crear un archivo temporal a partir del flujo de entrada estándar y generar el nombre del archivo creado.
Las líneas magic
o submagic
deberí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 magic
o submagic
tal 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 con
tmpfile = $(mktemp); cat mouse.jpg | …
- reescribiéndolo como
imageviewer =(cat mouse.jpg)
- reescribiéndolo como
echo mouse.jpg | xargs imageviewer
- usando una función o un binario para resolverlo, digamos definiendo
function 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 imageviewer
ser feh
o sxiv
o 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 bash
menos, con el uso de unsustitución de procesos:
utility <( some_other_utility )
Esto se presentaría utility
con unNombre del archivo. Cuando utility
abre 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.jpg
a 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.jpg
a imageviewer
se 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 xargs
esperaría con la ejecución imageviewer
hasta 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 submagic
en la pregunta, edité la respuesta.
Puede zsh
crear 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.jpg
es 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 elTMPSUFFIX
variable 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 submagic
similar 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 $TMPFILE
despué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