Este es mi caso de uso: la utilidad de línea de comando melt
puede aceptar un nombre de archivo, con la extensión .melt
en la línea de comando, y abrirlo; Como ejemplo, este es un test_p.melt
archivo adecuado:
colour:blue
out=24
colour:red
out=48
... que se abre y juega con melt test_p.melt
.
Ahora, la cuestión es que .melt
los archivos no admiten comentarios, lo cual me gustaría que hicieran (recibirá mensajes de error para cualquier línea que contenga un argumento no analizable, incluidos aquellos con, digamos, a #
). Así que aquí hay un test_c.melt
archivo comentado:
# master comment here
colour:blue # this is blue!
out=24
colour:red
out=48
Abrir esto melt
directamente da:
$ melt test_c.melt
Failed to load "# master comment here"
...
... y no se muestra ninguna pantalla azul.
Entonces pensé: bueno, puedo poner comentarios.de todos modosy luego usar la sustitución del proceso Bash para filtrar el archivo sed
y simplemente proporcionárselo a la melt
aplicación. Primero, probé una prueba con cat
, que tuvo éxito:
$ cat <(sed 's/#.*$//' test_c.melt)
colour:blue
out=24
colour:red
out=48
... se ve bien;pero, si lo intento con melt
, se da cuenta de mi engaño:
$ melt <(sed 's/#.*$//' test_c.melt)
Failed to load "/dev/fd/62"
Failed to load "/dev/fd/62"
Básicamente, melt obtuvo el nombre de archivo de la tubería que Bash proporcionó para la sustitución del proceso, pero desafortunadamente, lo que melt
hace es procesar argv[i]
directamente; y en el caso de un archivo, debe ver una .melt
extensión en el nombre del archivo; si no es así, el proceso falla.
Entonces mi pregunta es: ¿cómo podría usar la sustitución de procesos, para que el nombre de archivo de la tubería tenga una extensión específica, en este caso .melt
? Básicamente, como resultado de la sustitución, me gustaría tener un nombre de archivo de tubería /dev/fd/62.melt
, que creo que se aprobará.
NB: por supuesto, siempre puedo hacer:
sed 's/#.*$//' test_c.melt > test_c_temp.melt
melt test_c_temp.melt
... pero primero, hay dos comandos aquí, y me gustaría un canal de una sola línea; y por otro, me abre otro problema al pensar en eliminar archivos temporales después, lo cual no me gusta.
¿Es esto posible con la sustitución del proceso Bash, o de alguna manera con herramientas estándar de Linux?
Respuesta1
Una posibilidad sería señalar melt
un sistema de archivos que muestre copias modificadas de archivos.FUSIBLEes una forma genérica de crear un controlador de sistema de archivos implementado por un programa normal y que no requiere privilegios. Haymuchos sistemas de archivos FUSE alrededor, y es muy probable que uno de ellos pueda ayudarle. La idea es proporcionar un punto de montaje donde al leer un .melt
archivo se lee el archivo "real" pero con los comentarios filtrados.
scriptfsParece prometedor (pero nunca lo he usado). Algo como esto debería funcionar:
mkdir ~/uncommented-melt
scriptfs -p "$HOME/bin/uncomment-melt;&*.melt" ~/work ~/uncommented-melt
¿Dónde ~/work
está la raíz del árbol que contiene tus .melt
archivos y ~/bin/uncomment-melt
es?
#!/bin/sh
sed 's/#.*$//' "$1"
Luego, si tiene un archivo ~/work/test_c.melt
con comentarios, puede ejecutar melt ~/uncommented-melt/test_c.melt
.
Otros posibles sistemas de archivos FUSE útiles:
Respuesta2
Con el zsh
shell, puedes usar la =(...)
forma de sustitución de procesos (que usa archivos temporales en lugar de /dev/fd/x
archivos y canalizaciones) para la cual puedes especificar un sufijo:
(TMPSUFFIX=.melt; melt =(sed 's/#.*$//' test_c.melt))
Consulte info zsh TMPSUFFIX
(suponiendo que las info
páginas estén instaladas, es posible que necesite instalar un zsh-doc
paquete) para obtener más detalles.
Respuesta3
Bien, resulta que en mi caso específico, este tipo de scripts de fusión deben interpretarse estrictamente como argumentos de línea de comandos; por lo que solo el sed
del OP no es suficiente (además, hay otras cosas como perfiles que se pueden configurar). Así que esto es lo que terminé haciendo: probablemente pueda servir como inspiración en otros casos que cubriría el título del OP.
Finalmente me decidí por usar esto: crear un test.shmelt
archivo, que en realidad es un bash
script que contiene mi código de script comentado melt
; hacer que este archivo sea ejecutable chmod +x test.shmelt
; luego, después de editar el script, ejecútelo como ./test.shmelt
.
Al ejecutarse, creará un test.melt
archivo "limpio" en /tmp
y llamará melt
a este archivo en su lugar. Dado que melt
normalmente sigue ejecutándose en la terminal después del final de su programa, con una trampa en SIGINT este archivo temporal se puede limpiar cuando se presiona Ctrl-C (pero no es necesario).
De esa manera, todavía tengo comentarios; puede editar rápidamente el archivo fuente y ejecutar Melt y ver los resultados; y también tener un archivo "limpio" de comentarios, que puedo usar más adelante.
Aquí está el código de test.shmelt
:
#!/bin/bash
# call with: ./test.shmelt
#TMLTFILE="test.melt" # for final export
TMLTFILE="${0%%.shmelt}.melt" # for final export
function finished() { echo ; } ; # use this when testing or montaging to keep exported (tmp) .melt file; uncomment the below to remove the tmp file
#~ function finished() { rm /tmp/"$TMLTFILE"; echo "fin1 $0" ; } ; trap finished SIGINT ;
echo 'Remember `pulseaudio --start` to hear audio with `melt`!'
pulseaudio --check
if [ $? -ne 0 ]; then
pulseaudio --start
fi
DIRNAME=$(readlink -f $(dirname $0))
PROFILE="square_ntsc"
echo "
# the profile doesn't work from here;
# still has to be specified on command line
# but including it here so the path is saved for testing
#~ -profile
#~ ${PROFILE}
-video-track
# can avoid pixmap: here, but that s the producer;
# qimage: also works
# NB it is NOT '-out 1645'; but 'out=1645'!!
/media/myimg/%05d.bmp
in=0
out=1645
#~ length=1645
#~ loop=0
#~ eof=stop
-audio-track
/media/mysnd/snd.wav
in=0
out=1645
#~ loop=0
#~ eof=stop
#-consumer xml # doesn't work here
" | sed -e 's/#.*$//' -e 's/^[[:space:]]*//' -e '/^[[:space:]]*$/d' -e 's/[[:blank:]]*$//' > ${TMLTFILE}
# the sed: remove comments; remove indents; remove empty lines; remove spaces at end of line
# eof: one of: stop, loop, continue or pause (eof=stop)
# to loop, use `melt eof=loop ...` (but make sure first,
# that the edit as a whole stops - use xml to check!)
# due to caching issues, preview pieces (up to ~300 frames) like this:
melt eof=loop -profile ${PROFILE} ${TMLTFILE} in=200 out=400
# must have profile here, for checking w/ -consumer xml (else segfault)
# this command may add additional producers to the xml!:
## melt -profile ${PROFILE} ${TMLTFILE} -consumer xml
# use this to generate xml if needed:
#melt -profile ${PROFILE} $(cat ${TMLTFILE} | tr '\n' ' ') -consumer xml
# if exited normally, cleanup:
finished
Respuesta4
Ha pasado un tiempo, pero intentaré responder la pregunta del título de una manera que me haya resultado útil.
Esto está relacionado:¿Por qué la sustitución de procesos BASH no funciona con algunos comandos?
Entonces, el problema específico que estaba tratando de resolver era este:
- Tengo un conversor de imágenes;
- convierte de [insertar formato aleatorio] a formatos simples como BMP/PNM/TGA;
- Quiero convertir a JPEG, así que necesito encadenarlo con ImageMagick
convert
; - No quiero utilizar archivos temporales.
Entonces, desafortunadamente, a la herramienta no le gusta generar salida a stdout/fds/pipes porque deriva el formato de salida de la extensión del nombre del archivo de salida. Entonces, ¿cómo engañarlo?
Cree un enlace simbólico con la extensión adecuada /dev/fd/N
y utilícelo como "archivo temporal".
Ejemplo:
ln -s /dev/fd/4 temp.pnm
[TOOL] -i [INPUTFILE] -o temp.pnm 4>&1 | convert - [OUTPUT.JPG]