Estoy usando bash para obtener información desde audacious hasta conky para mostrarla (incluida la carátula del álbum). Obtengo la ruta al directorio del archivo de música de audacious, luego intento acceder a ese directorio para encontrar la carpeta.jpg; si lo encuentro, me preparo para mostrarlo. Desafortunadamente, no puedo confiar en nombres de rutas "bien formados". Ninguno de ellos tiene problemas desde la terminal, pero las evaluaciones que hace bash... Se ahoga con espacios duplicados ( ) ' / y probablemente otros, aunque la configuración actual parece funcionar - ok. Aquí está la función relevante:
GetArt ()
{
file_path=`audtool --current-song-tuple-data file-path` # get the path to the song
file_path=$(eval echo "${file_path}") # pre-expand to full path
cd "${file_path}"
if [[ ! -e "folder.jpg" ]]; # if no art work found
then
cp ~/Work/vinyl.png /tmp/cover.png # put in placeholder
else
convert "${file_path}""/folder.jpg" -resize 120x120 /tmp/cover.png # ready for showing
fi
}
¿Alguna idea, o sería más fácil sacar el cepillo de alambre y eliminar el óxido de mi compilador 'C'?
Probé con comillas dobles, comillas simples, comillas invertidas e incluso una construcción como:
code=$code \"\$filename\""
pero nada parece funcionar correctamente todavía. Afortunadamente, falla "bonito" porque simplemente aparece la imagen sustituta "no puedo encontrar arte", pero a veces las cosas eructan por todas partes hasta la siguiente canción o álbum.
Respuesta1
Puedes usar file_path="${file_path/#~/$HOME}"
para expandirjustoel ~
.
Por lo que yo puedo decir,expansión de tildees el único tipo de expansión que debe realizarse en la salida de audtool --current-song-tuple-data file-path
. Además, solo aparece un caso específico de notación de tilde: si la ruta que utiliza Audacious comienza con el directorio de inicio del usuario que ejecuta Audacious, esa parte de la ruta se reemplaza con a ~
en la salida de audtool
. desde elaudacious
yaudtool
Las páginas de manual no aclaran esto, he intentado acceder audtool
a rutas de salida con el prefijo ~username
de expansión de tilde y, afortunadamente, parece que nunca se hace ni siquiera eso. Digo "afortunadamente" porque significa que la situación es bastante simple.
Dado que la única transformación que debe realizarse en la salida de ese audtool
comando es reemplazar un principio~
con la ruta del directorio de inicio del usuario, puede simplemente escribir código en su secuencia de comandos que haga esa expansión por sí misma y, de lo contrario, deje la ruta sin modificar. . Descubrió que los nombres de los archivos de audio que puede reproducir pueden contener caracteres tratados especialmente por el shell, ysi reproduces archivos nombrados por otras personas,incluso puede dar lugar a una vulnerabilidad de seguridaden tu guión. Al no hacer que el shell ejecute (o incluso expanda) texto arbitrario que no sea de confianza, se evita ese problema por completo.
Hay varias maneras de expandirse ~
. Yo sugiero:
file_path="$(audtool --current-song-tuple-data file-path)" # might need tilde expansion
file_path="${file_path/#~/$HOME}" # do the tilde expansion, if needed
Esto realiza manualmente la única transformación que pueda ser necesaria. Específicamente, cuando la salida de audtool
comienza con a ~
, lo reemplaza con el directorio de inicio del usuario, obtenido al verificar el valor de la HOME
variable. Cuando la salida no comienza con a ~
, no se realiza ninguna expansión.
Tenga en cuenta que este enfoque,${file_path/#~/$HOME}
,nosería correcto si se usara como un intento de simular todas las formas de expansión de tilde, porque realizaría sustituciones incorrectas en la ~username
forma (y en algunas de las otras formas más oscuras). Sin embargo, siempre que haya rutas en la salida deaudtool
solo usen notación de tilde en el caso simple de designar el directorio de inicio del usuario actual (que creo que es el caso), entonces este enfoqueesapropiado y correcto para esos caminos.
La forma en que funciona es:
- En general,Bash se expandirá
${parameter/pattern/string}
en el valor deparameter
, pero conla parte que coincidepattern
reemplazadas constring
. Si ninguna pieza coincide con el patrón,parameter
se utiliza el valor exacto de. - Cuando
pattern
se escribe con un interlineado#
, solo se puede hacer coincidir comenzando desde el principio del valor deparameter
. (Hay otros caracteres además#
que son significativos en esta posición: a%
requeriría que el patrón coincida en el mismofin, y a/
haría que el patrón coincida y se reemplace tantas veces como aparezca en lugar de como máximo una vez). ~
no tiene ningún significado especial en un patrón y, por lo tanto, se trata literalmente, como un carácter que debe coincidir y reemplazarse.
Verexpansión de parámetrospara detalles.
Tenga en cuenta que el código que he escrito no hace nada para manejar el caso de audtool
producir una salida vacía, como sucede cuando no hay ninguna canción reproduciéndose actualmente (o, comoSimon Sudler mencionó, si hay un error). Sin embargo, no se interrumpe con una salida vacía ni interfiere con su posterior manejo. Entonces, si desea cubrir ese caso, aún puede hacerlo.
Finalmente, debo mencionar que he pasado por alto dos distinciones que creo que no son importantes para su caso de uso:
- Dado que
audtool
las rutas de 'provienen de Audacious, si estuvieras intentando la extraña situación de ejecutar Audacious como un usuario y ejecutarloaudtool
como otro, y de alguna manera configuraste D-Bus para que funcionara, entonces tendrías que preocuparte por~
referirte a una ruta diferente. directorio de inicio del usuario que el usuario que ejecuta el script. - Técnicamente hablando, la expansión de tilde para el usuario actual (que ocurre en un shell con
~
"sí mismo" o seguida inmediatamente por/
") no esbastanteequivalente a"$HOME"
. Los shells pueden intentar manejar el caso extraño en el queHOME
no está configurado. Bash intenta manejar esto y aun así producir una expansión correcta. Sin embargo, dudo que te importe la distinción para este propósito. Verexpansión de tildepara detalles.
Respuesta2
file_path
No es necesaria la reasignación de las variables. Hay 2 señales que pueden suceder y que podrían romper el guión:
- La variable está vacía porque
audtool
devuelve un error. - Devuelve
audtools
un directorio que contiene espacios en blanco. audtool
incluye~
para el directorio de inicio
Aquí una propuesta sobre cómo abordar estos temas:
GetArt ()
{
file_path="$(audtool --current-song-tuple-data file-path)"
file_path="$(readlink -f "$(bash -c "echo $file_path")")"
if [[ ! -d $file_path ]]; then
echo "error: $file_path does not exists"
exit 1
fi
folder_jpg="$file_path/folder.jpg"
if [[ ! -e "$folder_jpg" ]]; then
cp ~/Work/vinyl.png /tmp/cover.png
else
convert "$folder_jpg" -resize 120x120 /tmp/cover.png
fi
}
Maneja "$(command)"
los espacios en blanco en el nombre de la carpeta (si hay alguno). No lo use cd
dentro de un script, si no lo necesita. Siempre es una buena idea comprobar si la cadena de retorno es un directorio. En la mayoría de los casos, trabajar con la ruta absoluta es mejor y evita la ejecución de comandos en la carpeta incorrecta.
Notas sobre la ~
expansión en bash:
La expansión de la ~
es manejada por bash, por lo que readlink -f
no ayuda aquí. Por lo tanto, la variable que contiene ~
debe ejecutarse sin comillas para expandirse (actualicé el script). Por supuesto, esto se puede manejar en una sola línea...
# expansion from current bash
$ set -x; readlink -f ~; set +x
+ readlink -f /home/user
/home/user
+ set +x
# expansion will not work, with quoted ~
$ set -x; readlink -f '~'; set +x
+ readlink -f '~'
/home/user/~
+ set +x
# expansion from un-quoted ~ with sub-shell
$ set -x; readlink -f "$(bash -c "echo ~")"; set +x
++ bash -c 'echo ~'
+ readlink -f /home/user
/home/user
+ set +x