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 readlinkes 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$PWDal frente. La#./parte se quita./desde el frente de$1.fuente
realpath ../somethingdevuelve$PWD/../somethingcommand -v realpath >/dev/null 2>&1 || realpath() { ... }Estos tres sencillos pasos resolverán este y muchos otros problemas de OS X:
brew install coreutilsgrealpath .(3) se puede cambiar a solo
realpath, ver (2) salidafuente
$( cd "$(dirname "$0")" ; pwd -P )listas para usar" que funcionan bien para mí.XXXy alguiencd xxxentoncespwdvolverá.../xxx. Excepto por esta respuesta, todas las soluciones anteriores regresanxxxcuando 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
localpara 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 lorealpathharía. Con homebrewcoreutilsinstalado, intenteln -s /var/log /tmp/linkexampleentoncesrealpath /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$0contiene una sola comilla, por ejemplo. Un ejemplo muy simple: pruebe su versión/tmp/'/test.shy llame/tmp/'/test.shpor su ruta completa./tmp/'.sh.Dado que hay un camino real como otros han señalado:
Makefile:
Luego compile
makey coloque un enlace suave con:ln -s $(pwd)/realpath /usr/local/bin/realpathfuente
gcc realpath.c -o /usr/local/bin/realpath?/usr/local/binUsa 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
brewinstalado, 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
dirnamedará el nombre del directorio de/path/to/file, es decir/path/to.cd /path/to; pwdasegura que la ruta sea absoluta.basenamele 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/fooel padre de cualquier ruta a la que/foo/link_to_other_directoryapunte el enlace simbólico .readlink -fyrealpathresuelva 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 ...echono debería también ser perpetrado...las referencias a los padres antes de resolver los enlaces simbólicos, no después; intente esto con Homebrewcoreutilsinstalado, cree un enlace yln -s /var/log /tmp/linkexampleluego ejecuterealpath /tmp/linkexample/../; esto imprime/private/var. Pero su función produce/tmp/linkexample/..en su lugar, porquepwdtodavía se muestra/tmp/linkexampledespué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
realpathreemplazo en OS X, uno que funcione correctamente en rutas con enlaces simbólicos y referencias de padres como loreadlink -fharía . Esto incluye resolver enlaces simbólicos en la ruta antes de resolver las referencias principales; por ejemplo, si ha instalado lacoreutilsbotella de cerveza casera, ejecute:Tenga en cuenta que se
readlink -fha resuelto/tmp/linkeddirantes de resolver la..referencia del directorio principal. Por supuesto, no hay esreadlink -fen Mac cualquiera .Entonces, como parte de la implementación de a bash,
realpathvolví 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 -fhace 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-toy--relative-baseapoyo, 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. Simplementepwdhace lo mismo queecho $(pwd)sin tener que generar una segunda copia del shell. Además, no citar el argumento deechoes 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/…realpathde 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.