2009-01-07 12 views
10

Lo que me gustaría hacer es incluir la configuración de un archivo en mi shell de bash interactivo actual de esta manera:¿Cómo puede una secuencia de comandos bash saber el directorio en el que está instalado cuando se obtiene con. ¿operador?

$. /path/to/some/dir/.settings

El problema es que el script .settings también necesita utilizar el "." operador para incluir otros archivos como este:

. .extra_settings

¿Cómo hago referencia a la ruta relativa para .extra_settings en el archivo .settings? Estos dos archivos siempre se almacenan en el mismo directorio, pero la ruta a este directorio será diferente dependiendo de dónde se instalaron estos archivos.

El operador siempre conoce/path/to/some/dir/como se muestra arriba. ¿Cómo puede saber el archivo .settings el directorio donde está instalado? Preferiría no tener un proceso de instalación que registre el nombre del directorio instalado.

Respuesta

17

Creo $(dirname "$BASH_SOURCE") va a hacer lo que quiera, siempre y cuando el archivo está en fuente es no un enlace simbólico.

Si el archivo está en fuente puede ser un enlace simbólico, se puede hacer algo como lo siguiente para obtener el verdadero directorio:

PRG="$BASH_SOURCE" 
progname=`basename "$BASH_SOURCE"` 

while [ -h "$PRG" ] ; do 
    ls=`ls -ld "$PRG"` 
    link=`expr "$ls" : '.*-> \(.*\)$'` 
    if expr "$link" : '/.*' > /dev/null; then 
     PRG="$link" 
    else 
     PRG=`dirname "$PRG"`"/$link" 
    fi 
done 

dir=$(dirname "$PRG") 
+0

Perfecto. $ (dirname "$ BASH_SOURCE") es lo que yo era exactamente lo que estaba buscando. Para mi propósito, no me importan mucho los enlaces simbólicos. Gracias a todos los que respondieron. Muy buenas respuestas aquí. – Gary

+8

Para resolver enlaces simbólicos, puede hacer lo siguiente: 'dir = $ (dirname $ (readlink -f" $ BASH_SOURCE "))' –

0

Intenté jugar con variantes de $ (dirname $ 0) pero falla cuando el archivo .settings se incluye con ".". Si estuviera ejecutando el archivo .settings en lugar de incluirlo, esta solución funcionaría. En cambio, $ (dirname $ 0) siempre devuelve ".", Que significa directorio actual. Esto falla al hacer algo como esto:

$ cd/ $. /some/path/.settings

+0

hmm, lástima. No tengo idea entonces –

2

Otra forma de resolver el problema: si está utilizando "." con el fin de establecer las variables de entorno, de otra manera estándar de hacer esto es tener la secuencia de comandos de eco comandos de ajuste de variables, por ejemplo:

# settings.sh 
echo export CLASSPATH=${CLASSPATH}:/foo/bar 

entonces eval la salida:

eval $(/path/to/settings.sh) 

Eso es como paquetes como modules trabajo . De esta manera también hace que sea fácil para apoyar conchas derivados de sh (X=...; export X) y CSH (setenv X ...)

+0

Correcto, así es como INN lo hace. "innconfvar" (creo que así se llama) emite las variables de configuración como comandos sh, csh o perl. –

+0

Me gusta esta idea. Sin embargo, no lo estoy usando porque los efectos secundarios harían que el archivo .settings fuera aún más ilegible, ya que para empezar tiene muchos escapes. Vea abajo. – Gary

0

Este tipo de obras. Funciona en el sentido de que puede usar la sintaxis $ (dirname $ 0) dentro del archivo .settings para determinar su origen, ya que está ejecutando este script en un nuevo shell. Sin embargo, añade una capa adicional de convolución donde tiene que cambiar líneas tales como:

export MYDATE=$(date) 

a

echo "export MYDATE=\$(date)" 

Quizás esta es la única manera?

+0

Parece que también agregaría complejidad si estuviera buscando funciones de shell. (Estaba buscando una forma de hacer esto que funcione tanto con ksh como con bash ...) – mpontillo

6

Aquí es lo que podría ser una solución elegante:

script_dir=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd) 

Esto, sin embargo, el trabajo en caso de procurarse enlaces.En ese caso, se podría hacer

script_dir=$(readlink -f $(readlink "${BASH_SOURCE[0]}") 

Ten cuidado que las matrices como ${array[x]} no son compatibles con POSIX. Por supuesto, la matriz BASH_SOURCE solo está disponible en Bash.

+0

¿Por qué se necesitaría el '[0]'? @JasonDay no lo tiene en su respuesta. – asmeurer

+3

BASH_SOURCE es una matriz que representa la pila de llamadas y el primer elemento es la secuencia de comandos actualmente en ejecución. –

Cuestiones relacionadas