Estoy tratando de obtener la ruta absoluta al script que se está ejecutando actualmente en OS X.
Vi muchas respuestas a su favor readlink -f $0
. Sin embargo, dado que OS X readlink
es igual que BSD, simplemente no funciona (funciona con la versión de GNU).
¿Existe una solución inmediata para esto?
$( cd "$(dirname "$0")" ; pwd -P )
Respuestas:
Hay una
realpath()
función C que hará el trabajo, pero no veo nada disponible en la línea de comandos. Aquí hay un reemplazo rápido y sucio:Esto imprime la ruta textualmente si comienza con a
/
. De lo contrario, debe ser una ruta relativa, por lo que antepone$PWD
al frente. La#./
parte se quita./
desde el frente de$1
.fuente
realpath ../something
devuelve$PWD/../something
command -v realpath >/dev/null 2>&1 || realpath() { ... }
Estos tres sencillos pasos resolverán este y muchos otros problemas de OS X:
brew install coreutils
grealpath .
(3) se puede cambiar a solo
realpath
, ver (2) salidafuente
$( cd "$(dirname "$0")" ; pwd -P )
listas para usar" que funcionan bien para mí.XXX
y alguiencd xxx
entoncespwd
volverá.../xxx
. Excepto por esta respuesta, todas las soluciones anteriores regresanxxx
cuando lo que realmente desea esXXX
. ¡Gracias!realpath
, ¿qué sucede cuando es casi seguro que necesitará otros elementoscoreutils
? ¿Reescribir esas funciones en bash también? : PUgh. Encontré las respuestas anteriores un poco deficientes por algunas razones: en particular, no resuelven múltiples niveles de enlaces simbólicos, y son extremadamente "Bash-y". Si bien la pregunta original pide explícitamente un "script Bash", también menciona el tipo BSD de Mac OS X, que no es GNU
readlink
. Así que aquí hay un intento de una portabilidad razonable (lo he comprobado con bash como 'sh' y guión), resolviendo un número arbitrario de enlaces simbólicos; y también debería funcionar con espacios en blanco en la (s) ruta (s), aunque no estoy seguro del comportamiento si hay espacios en blanco en el nombre base de la utilidad en sí, así que tal vez, um, ¿evitarlo?Espero que pueda ser de alguna utilidad para alguien.
fuente
local
para variables definidas dentro de la función para no contaminar el espacio de nombres global. Ejlocal OURPWD=...
. Funciona al menos para bash.BASENAME=$(basename "$LINK")
inside the while" y usarlo en el segundo setter LINK y el setter..
las referencias de los padres como lorealpath
haría. Con homebrewcoreutils
instalado, intenteln -s /var/log /tmp/linkexample
entoncesrealpath /tmp/linkexample/../
; esto imprime/private/var
. Pero su función produce/tmp/linkexample/..
en su lugar, porque..
no es un enlace simbólico.Una variante más amigable con la línea de comandos de la solución Python:
fuente
python -c "import os; import sys; print(os.path.realpath(sys.argv[1]))"
Estaba buscando una solución para usar en un script de provisión del sistema, es decir, ejecutar antes de que Homebrew esté instalado. Al carecer de una solución adecuada, simplemente descargaría la tarea a un lenguaje multiplataforma, por ejemplo, Perl:
Más a menudo lo que realmente queremos es el directorio contenedor:
fuente
FULLPATH=$(perl -e "use Cwd 'abs_path'; print abs_path('$0')")
. ¿Alguna razón en contra?''
no es a prueba de balas. Se rompe si$0
contiene una sola comilla, por ejemplo. Un ejemplo muy simple: pruebe su versión/tmp/'/test.sh
y llame/tmp/'/test.sh
por su ruta completa./tmp/'.sh
.Dado que hay un camino real como otros han señalado:
Makefile:
Luego compile
make
y coloque un enlace suave con:ln -s $(pwd)/realpath /usr/local/bin/realpath
fuente
gcc realpath.c -o /usr/local/bin/realpath
?/usr/local/bin
Usa Python para conseguirlo:
fuente
En macOS, la única solución que he encontrado para esto que maneja de manera confiable los enlaces simbólicos es usando
realpath
. Dado que esto requierebrew install coreutils
, simplemente automaticé ese paso. Mi implementación se ve así:Este error si no se ha
brew
instalado, pero también puede instalarlo. Simplemente no me sentía cómodo automatizando algo que cursa código rubí arbitrario de la red.Tenga en cuenta que esta es una variación automática de la respuesta de Oleg Mikheev .
Una prueba importante
Una buena prueba de cualquiera de estas soluciones es:
ln -s
) a ese archivo¿La solución elimina la referencia al enlace simbólico y le proporciona el directorio original? Si es así, funciona.
fuente
dirname
dará el nombre del directorio de/path/to/file
, es decir/path/to
.cd /path/to; pwd
asegura que la ruta sea absoluta.basename
le dará solo el nombre del archivo/path/to/file
, es decirfile
.fuente
Entonces, como puede ver arriba, lo intenté hace unos 6 meses. Lo olvidé por completo hasta que volví a necesitar algo similar. Estaba completamente sorprendido de ver cuán rudimentario era; He estado aprendiendo a codificar de forma bastante intensiva durante aproximadamente un año, pero a menudo siento que tal vez no he aprendido nada cuando las cosas están en su peor momento.
Quitaría la 'solución' anterior, pero realmente me gusta que sea un registro de lo mucho que realmente he aprendido en los últimos meses.
Pero yo divago. Me senté y resolví todo anoche. La explicación en los comentarios debería ser suficiente. Si desea realizar un seguimiento de la copia en la que sigo trabajando, puede seguir esta esencia. Probablemente esto haga lo que necesita.
fuente
..
las referencias principales; por ejemplo,/foo/link_to_other_directory/..
se resuelve como/foo
el padre de cualquier ruta a la que/foo/link_to_other_directory
apunte el enlace simbólico .readlink -f
yrealpath
resuelva cada componente de la ruta comenzando en la raíz y actualizando los destinos de enlace anteriores al resto que aún se está procesando. Agregué una respuesta a esta pregunta reimplementando esa lógica.realpath para Mac OS X
Ejemplo con ruta relacionada:
Ejemplo con carpeta de inicio
fuente
..
ella no produce la respuesta correcta, así que agregué una verificación si la ruta dada es un directorio:if test -d $path ; then echo $(cd "$path"; pwd) ; else [...]
"$(dirname $(dirname $(realpath $0)))"
que funciona, así que necesito algo más ...echo
no debería también ser perpetrado...
las referencias a los padres antes de resolver los enlaces simbólicos, no después; intente esto con Homebrewcoreutils
instalado, cree un enlace yln -s /var/log /tmp/linkexample
luego ejecuterealpath /tmp/linkexample/../
; esto imprime/private/var
. Pero su función produce/tmp/linkexample/..
en su lugar, porquepwd
todavía se muestra/tmp/linkexample
después del cd.Esto parece funcionar para OSX, no requiere ningún binario y se extrajo de aquí
fuente
Me gusta esto:
fuente
Necesitaba un
realpath
reemplazo en OS X, uno que funcione correctamente en rutas con enlaces simbólicos y referencias de padres como loreadlink -f
haría . Esto incluye resolver enlaces simbólicos en la ruta antes de resolver las referencias principales; por ejemplo, si ha instalado lacoreutils
botella de cerveza casera, ejecute:Tenga en cuenta que se
readlink -f
ha resuelto/tmp/linkeddir
antes de resolver la..
referencia del directorio principal. Por supuesto, no hay esreadlink -f
en Mac cualquiera .Entonces, como parte de la implementación de a bash,
realpath
volví a implementar lo que hace una llamada decanonicalize_filename_mode(path, CAN_ALL_BUT_LAST)
función GNUlib , en Bash 3.2; esta es también la llamada de función quereadlink -f
hace GNU :Incluye detección de enlace simbólico circular, saliendo si la misma ruta (intermedia) se ve dos veces.
Si todo lo que necesita es
readlink -f
, puede utilizar lo anterior como:Porque
realpath
, también necesitaba--relative-to
y--relative-base
apoyo, lo que le brinda rutas relativas después de canonicalizar:Incluí pruebas unitarias en mi solicitud de revisión de código para este código .
fuente
Basado en la comunicación con el comentarista, estuve de acuerdo en que es muy difícil y no tiene una forma trivial de implementar un camino real que se comporta totalmente igual que Ubuntu.
Pero la siguiente versión, puede manejar casos de esquina, la mejor respuesta no puede y satisfacer mis necesidades diarias en macbook. Pon este código en tu ~ / .bashrc y recuerda:
fuente
echo
. Simplementepwd
hace lo mismo queecho $(pwd)
sin tener que generar una segunda copia del shell. Además, no citar el argumento deecho
es un error (perderá cualquier espacio en blanco inicial o final, cualquier carácter de espacio en blanco interno adyacente y se expandirán los comodines, etc.). Ver más stackoverflow.com/questions/10067266/…realpath
de un directorio inexistente.dir=$(dirname "$1"); file=$(basename "$1")
lugar de la sintaxis de comillas invertidas, obsoleta. También observe la cita correcta de los argumentos, nuevamente.