¿Cómo puedo recuperar el nombre de archivo absoluto en un script de shell en Mac OS X?

19

Me gustaría recuperar el nombre absoluto del archivo de script que se está ejecutando actualmente. Los enlaces también deben resolverse.

En Linux, esto parece hacerse así:

$(readlink -mn "$0")

pero readlinkparece funcionar de manera muy diferente en Mac OS X.

He leído que esto se hace usando

$(realpath $0)

en BSD pero eso tampoco funciona. Mac OS X no tiene realpath.

¿Alguna idea?

Huxi
fuente
1
Vea esta pregunta en SO: stackoverflow.com/questions/799679/…
Telemachus
Aún más opciones: stackoverflow.com/questions/7665/…
Gerhard Burger

Respuestas:

19

Hago trampa y uso perl para esto:

#!/bin/bash
dirname=`perl -e 'use Cwd "abs_path";print abs_path(shift)' $0`
echo $dirname

Uno pensaría que simplemente escribiría todo el guión en perl, y a menudo lo hago, pero no siempre.

ericslaw
fuente
Esto funciona, muchas gracias. Te daré un voto positivo tan pronto como pueda. ¿Alguien tiene una forma de "caparazón puro" para hacer esto?
Huxi
1
Me temo que esto es tan bueno como se pone. (Dados los muchos hacks de "línea pura" de varias líneas que uno puede encontrar en Google.)
Arjan el
Otra posibilidad (aunque fea) es atravesar el camino '..', memorizando (a través de la recursión o una matriz) hasta que '..' devuelva el mismo archivo que acaba de tener (es decir: está en la parte superior), luego vuelva ensamblando el camino a medida que avanzas. He visto el software de copia de seguridad Networker de Legato haciendo esto durante strace como un método para obtener una ruta 'verdadera' (pero tal vez no absoluta). Pero sería mucho más código que el anterior.
ericslaw
No estoy seguro de por qué alguien modificó el código para usar $ 1 en lugar de $ 0. ¿No es $ 1 el primer argumento para el script bash? Quería la ruta al script bash en ejecución, no su primer argumento.
ericslaw
27
#!/usr/bin/env bash
scriptDir="$(cd "$(dirname "$0")" && pwd -P)"
jhclark
fuente
Funciona en MacOSX también.
Alexar
1
Esto es super! Hay muchas otras respuestas demasiado complicadas flotando.
Jason S
3
Esto solo funciona para archivos en un directorio con enlace simbólico, no para archivos con enlace simbólico en general
Gerhard Burger
1
También es útil unset -v CDPATHantes del CD, ya que el CD puede causar una salida no deseada si se establece CDPATH.
Binary Phile
Para lidiar con al menos una sola capa de enlace simbólico del archivo, también puede probar de manera compatible con readlink (los Mac no tienen -f): scriptDir=$(unset -v CDPATH; cd "$(dirname "$(readlink "$BASH_SOURCE" || echo "$BASH_SOURCE)")" && pwd -P)
Binary Phile
0

Esto maneja combinaciones de enlaces simbólicos, y funciona en archivos y carpetas:

#!/usr/bin/env bash
realpath()
{
    if ! pushd $1 &> /dev/null; then 
        pushd ${1##*/} &> /dev/null
        echo $( pwd -P )/${1%/*}
    else
        pwd -P
    fi
    popd > /dev/null
}

Pero no admite realpath's --relative-to. Esto requeriría la conversión descrita aquí .

Oliver
fuente
0

Otro enfoque:

# Install.
brew install coreutils

# Use the GNU variant.
grealpath --help
FMc
fuente