¿Qué hace $ {0% / *} en los scripts de shell?


17

Lo siento si esta es una pregunta estúpida, pero la busqué sin éxito.

¿Qué hace exactamente la segunda línea?

#!/bin/sh
cd ${0%/*} || exit 1

Sé que el primero es el shebang, el segundo intenta cambiar el directorio pero la parte confusa es ${0%/*}.

¿Me puede explicar esa segunda línea?


2
Como explicó Andrea en una respuesta, $ {0% / *} se traduce en la ruta del directorio prefijada al nombre del script mientras se invoca. Una alternativa es usar el dirnamecomando incorporado como$(dirname $0)
aprendiendo el

@alwayslearning: ¿Qué shell y versión de shell está utilizando que dirnameestá integrado? Ciertamente no está en Bash v4.3.11, que es el shell predeterminado en Ubuntu Trusty.
David Foerster

Mis disculpas por la confusión, acabo de comprobar que dirnameno es un shell incorporado.
aprendiendo el

Respuestas:


27

${0}es el primer argumento del guión, es decir, el nombre o la ruta del guión. Si inicia la secuencia de comandos como path/to/script.sh, a continuación, ${0}será exactamente esa cadena: path/to/script.sh.

La %/*parte modifica el valor de ${0}. Significa: tomar todos los caracteres hasta que /siga un nombre de archivo. En el ejemplo anterior, ${0%/*}será path/to.

Puedes verlo en acción en tu shell:

$ x=path/to/script.sh
$ echo "${x%/*}"
path/to

Sh admite muchos otros tipos de "sustitución de parámetros". Aquí está, por ejemplo, cómo tomar el nombre del archivo en lugar de la ruta:

$ echo "${x##*/}"
script.sh

En general, %y %%elimina los sufijos, mientras que #y ##elimina los prefijos. Puede leer más sobre la sustitución de parámetros .


2
Esta "|| salida 1" parece ser innecesaria: si no sería posible cambiar dir $? es igual a 1.
Josef Klimuk

2
Sería bueno mencionar que la construcción está documentada como "Eliminar patrón de prefijo / sufijo coincidente" en el manual. También es una buena manera de recordar cuál es cuál es # es shift 3 ( izquierda de $),% es shift 5 ( derecha de $), al menos en el teclado de EE. UU.
chexum

1
@JosefKlimuk: || exit 1 podría ser necesario porque cdpodría salir con el estado 2, no 1, por error. Sin embargo, estoy de acuerdo en que no es muy útil (por lo general, a los programas no les importan los estados de salida específicos). ¿Probablemente esto es parte de un script más grande?
Andrea Corbellini

1
@AndreaCorbellini Seguramente correcto. Casi la única forma en que puede ser útil es como parte de un script más grande. Un script que solo cambia el directorio actual no tiene ningún efecto, porque solo afecta al shell que ejecuta ese script. El proceso padre nunca lo ve.
hvd
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.