Hacer referencia a un archivo relativo a la ejecución de un script

94

En un script bash que estoy escribiendo, utilizo sourcepara incluir la variable definida en un archivo de configuración. El script que se ejecutará es act.sh, mientras que el script que se sourced es act.conf.sh, así que en act.shtengo:

source act.conf.sh

Sin embargo, esto solo funciona cuando se ejecuta act.shen el directorio que lo contiene, ya que act.conf.shse refiere al archivo ubicado debajo del directorio de trabajo. ¿Existe una solución para hacer que se refiera al archivo relativo al script en ejecución sin invocarlo cd? Gracias.

Ryan Li
fuente

Respuestas:

116

Consulte: Entrada n.º 28 de las preguntas frecuentes de BASH: "¿Cómo determino la ubicación de mi script? Quiero leer algunos archivos de configuración desde el mismo lugar".

Cualquier solución no va a funcionar el 100% del tiempo:

Es importante darse cuenta de que, en el caso general, este problema no tiene solución. Cualquier enfoque del que haya oído hablar, y cualquier enfoque que se detalla a continuación, tiene fallas y solo funcionará en casos específicos. En primer lugar, intente evitar el problema por completo al no depender de la ubicación de su script.

Si necesita escribir una herramienta muy reutilizable, entonces tomar la ruta correcta como parámetro para su script será el método más confiable .

Suponiendo que su script solo se ejecutará desde ciertos shells, y solo con un poco de flexibilidad requerida, probablemente pueda relajar algo de esta paranoia. Todavía es bueno mirar sus opciones. Hay patrones comunes que la gente usa que son particularmente problemáticos.

En particular, las preguntas frecuentes recomiendan evitar la $0variable de uso muy común :

Nada de lo que lea $0será a prueba de balas, porque en $0sí mismo no es confiable.

Como alternativa, puede usar $BASH_SOURCEen su lugar. Algo como esto:

source "${BASH_SOURCE%/*}/act.conf.sh"

También hay algunas advertencias en esta solución. Consulte la página de preguntas frecuentes para ver las compensaciones entre las diferentes soluciones. Parece que se recomiendan cden combinación con $BASH_SOURCEen los casos en que funcionará para usted, ya que obtiene una condición de error útil cuando no se expande correctamente.

Ignacio Vázquez-Abrams
fuente
1
Gracias, usaría readlink. No pude determinar las palabras clave para buscar, así que publiqué la pregunta aquí ....
Ryan Li
9
¿Puedes incluir la información relevante en la respuesta en caso de que las preguntas frecuentes de bash no estén disponibles?
Merlyn Morgan-Graham
3
Link recomienda:, cd "${BASH_SOURCE%/*}" || exito read somevar < "${BASH_SOURCE%/*}/etc/somefile"Link desaconseja rotundamente $0 "Nada que diga $ 0 será a prueba de balas, porque $ 0 en sí mismo no es confiable".
ThorSummoner
10
¿Qué hace% / * después de BASH_SOURCE y cómo?
Silicomancer
34

Vea esto: Bash: ¿Cómo _mejor_ incluir otros scripts?

Sugiero usar:

source $(dirname $0)/act.conf.sh
vagovszkym
fuente
8
Esta no es la respuesta que busca. $0es intrínsecamente defectuoso. Vea la respuesta más votada y aceptada para saber por qué, o simplemente lea mywiki.wooledge.org/BashFAQ/028 : una breve solución para la pregunta es algo así comosource "${BASH_SOURCE%/*}/act.conf.sh"
Merlyn Morgan-Graham
5

Intente lo siguiente:

source ${BASH_SOURCE[0]/%act.sh/act.conf.sh}
Despistado
fuente