No se puede acceder a una variable (pasada) en el script bash

No se puede acceder a una variable (pasada) en el script bash

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 elaudaciousyaudtoolLas páginas de manual no aclaran esto, he intentado acceder audtoola rutas de salida con el prefijo ~usernamede 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 audtoolcomando 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 audtoolcomienza con a ~, lo reemplaza con el directorio de inicio del usuario, obtenido al verificar el valor de la HOMEvariable. 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 ~usernameforma (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 coincidepatternreemplazadas con string. Si ninguna pieza coincide con el patrón, parameterse utiliza el valor exacto de.
  • Cuando patternse escribe con un interlineado #, solo se puede hacer coincidir comenzando desde el principio del valor de parameter. (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 audtoolproducir 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:

  1. Dado que audtoollas rutas de 'provienen de Audacious, si estuvieras intentando la extraña situación de ejecutar Audacious como un usuario y ejecutarlo audtoolcomo 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.
  2. 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 que HOMEno 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_pathNo es necesaria la reasignación de las variables. Hay 2 señales que pueden suceder y que podrían romper el guión:

  1. La variable está vacía porque audtooldevuelve un error.
  2. Devuelve audtoolsun directorio que contiene espacios en blanco.
  3. audtoolincluye ~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 cddentro 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 -fno 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

información relacionada