Explicación de $(cd $(dirname $0); pwd)

En muchos scripts de shell, es frecuente encontrar la siguiente instrucción:

directorioBase=$(cd $(dirname $0); pwd)
...

Esta instrucción obtiene la ruta absoluta del directorio donde se encuentra el script. ¿Cómo se entiende? ¿Por qué no usar directamente pwd para obtener la ruta actual?

Desglose de la instrucción

Basado en la explicación de explainshell.com para cd $(dirname $0); pwd, se descompone de la siguiente manera.

  • dirname elimina, del nombre de ruta de un archivo, el primer / contando de derecha a izquierda y todo lo que le sigue. Consultando la ayuda de dirname se ven ejemplos como:

    dirname /usr/bin/          → "/usr"
    dirname dir1/str dir2/str  → "dir1" seguido de "dir2"
    dirname stdio.h            → "."
    
    
  • $0 es un parámetro posicional en bash shell que endica el comando mismo ingresado en la línea de comandos. Los demás son $1, $2, etc., que representan el primer, segundo argumento, etc. Por ejemplo, en el comando:

    bash prueba.sh 10 9
    
    

    $0 es prueba.sh, $1 es 10 y $2 es 9.

  • pwd imprime la ruta absoluta del directorio actual.

Con el análisis anterior, ¿cómo se interpreta el comando completo? Supongamos que tenemos el siguiente script script.sh en el directorio ~/DTS/codigo:

#!/bin/bash
directorioBase=$(cd $(dirname $0); pwd)
echo "directorioBase $directorioBase"

Al ejecutar ./script.sh en la terminal, la salida sería:

usuario@opensuse:~/DTS/codigo$ ./script.sh
directorioBase /home/usuario/DTS/codigo

Observe dos elementos clave al ejecutar el script:

  • La ruta desde donde se invoca el script. En este caso, el directorio actual es ~/DTS/codigo/.
  • El comando usado para invocarlo: ./script.sh.

Con esto, $(dirname $0) devuelve ., entonces cd $(dirname $0) equivale a cd ., es decir, cambiar al directorio ~/DTS/codigo. Posteriormente pwd imprime la ruta absoluta de ese directorio, que es la del script.

¿Por qué no usar pwd directamente?

Considere el siguiente hecho fundamental:

Ejecutar un script de shell equivale a escribir cada una de sus instrucciones en la terminal desde el directorio actual donde se invocó el script.

Si modificamos el script anterior así:

#!/bin/bash
directorioBase=$(cd $(dirname $0); pwd)
echo "directorioBase $directorioBase"
echo "pwd $pwd"

Y lo ejecutamos desde ~/DTS con el comando codigo/script.sh, la salida será:

usuario@opensuse:~/DTS$ codigo/script.sh
directorioBase /home/usuario/DTS/codigo
pwd /home/usuario/DTS

El segundo pwd no corresponde al directorio del script, sino al directorio desde donde se escribió el comando. Como indica el hecho fundamental, al ejecuatr el script desde ~/DTS, cada instrucción se ejecuta como si se hubiera tecleado en ese mismo directorio. Por lo tanto, el pwd dentro del script devuelve la ruta actual de la terminal, no la del script.

La razón por la que no se puede usar pwd directamente para obtener el directorio del script es que si se invoca el script desde un directorio diferente, se obtiene la ruta desde donde se llamó, no la del script en sí.

Etiquetas: bash shell dirname pwd scripts

Publicado el 6-18 03:53