Obtener la ruta del script actual cuando se ejecuta a través de un enlace simbólico


59

Tengo una utilidad que consta de un par de directorios con algunos scripts de bash y archivos de soporte que se implementarán en varias máquinas, posiblemente en un directorio diferente en cada máquina. Los scripts deben poder hacer referencia a las rutas relativas a ellos mismos, por lo que necesito poder obtener la ruta al archivo que se está ejecutando actualmente.

Soy consciente del dirname $0idioma que funciona perfectamente cuando mi script se llama directamente. Desafortunadamente, existe el deseo de poder crear enlaces simbólicos a estos scripts desde un directorio totalmente diferente y todavía tener la lógica de ruta relativa de trabajo.

Un ejemplo de la estructura general general es el siguiente:

/
 |-usr/local/lib
 |  |-foo
 |  |  |-bin
 |  |  |  |-script.sh
 |  |  |-res
 |  |  |  |-resource_file.txt
 |-home/mike/bin
 |  |-link_to_script (symlink to /usr/local/lib/foo/bin/script.sh)

¿Cómo puedo hacer referencia confiable /usr/local/lib/foo/res/resource_file.txtde script.shsi es invocado por /usr/local/lib/foo/bin/script.sho ~mike/bin/link_to_script?

Respuestas:


80

Pruebe esto como una solución de uso general:

DIR="$(cd "$(dirname "$0")" && pwd)"

En el caso específico de los siguientes enlaces simbólicos, también puede hacer esto:

DIR="$(dirname "$(readlink -f "$0")")"

Funciona perfectamente y es mucho más simple que las cosas que estaba intentando. ¡Gracias!
Mike Deck

@MikeDeck Disfruta. Tenga en cuenta que solucioné algunos problemas de citas desde la primera publicación ... puede usar una opción de la última edición en caso de que tenga espacios u otros caracteres extraños en su camino en algún momento. Incluso si no importa para este proyecto, ¡puede copiar el código de sus propios scripts en el futuro y tener la mejor opción es importante!
Caleb

1
Debo aclarar, el segundo funciona perfectamente. La primera solución que diste no funciona para enlaces simbólicos en mi sistema.
Mike Deck

44
@MikeDeck: La primera solución funciona para el caso típico de tener varios directorios enlazados como parte de la ruta, pero no ayudará si el binario final es un enlace simbólico. De eso se encarga el segundo.
Caleb

1
No funciona si el archivo de script es sourced (p $ source ./sript.sh. Ej. ) Esto funciona para ambos casos:DIR="$(cd "$(dirname "$BASH_SOURCE")" && pwd)"
FractalSpace

7

una línea:

cd $(dirname $([ -L $0 ] && readlink -f $0 || echo $0))

2
Las respuestas de una línea generalmente no son las más útiles. Considere ampliar su respuesta para incluir explicaciones, enlaces o documentación que respalde aún más su solución sugerida.
HalosGhost

1
en realidad, no necesita hacer esto, la versión de enlace de
lectura

3

readlink -f no funciona para mí, tengo este error:

readlink: illegal option -- f
usage: readlink [-n] [file ...]

Pero esto funciona bien:

DIR="$(dirname "$(readlink "$0")")"
echo $DIR

3
Entonces estás en una Mac y esto debería responder a tu pregunta .
Isaac

Sí, estoy en MacOs @isaac, pero no tengo ninguna pregunta. Publiqué el comando que funciona de mi lado.
Kevin Campion el

0

Una pequeña adición al script anterior. La opción -P para pwd sigue enlaces simbólicos

DIR="$(cd "$(dirname "$0")" && pwd -P)"

77
Esto solo funciona cuando el enlace simbólico es parte de la estructura de directorios. No funciona cuando el archivo en sí está vinculado.
Oliver Gondža
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.