2 votos

Cómo determinar la ruta absoluta de un archivo en un shell script

Estoy escribiendo un script genérico que puede recibir rutas absolutas y relativas (al directorio de trabajo actual) de archivos existentes.

Necesito una forma segura de convertir todas esas rutas pasadas en rutas absolutas porque necesito pasar las rutas al comando "open", que no pasará el directorio actual a la aplicación lanzada.

Una idea que se me ha ocurrido es comprobar si la ruta empieza por "/", y si no es así, anteponerle la ruta del directorio de trabajo actual.

Sin embargo, me pregunto si hay una solución más inteligente para esto. Además, como soy bastante inexperto con los scripts de shell y las herramientas relacionadas, ni siquiera sé cómo comprobar si el valor de una variable empieza por "/". Estoy buscando una solución portátil para ejecutar en varios Mac, por lo que la instalación de herramientas adicionales o la configuración sería menos que ideal.

¿Puede alguien sugerir un script estándar que utilice sólo herramientas de envío y que tome una variable (llamémosla $ruta) y la convierta en una ruta absoluta si no lo es ya?

2voto

Una opción sería instalar coreutils y utilizar greadlink -f . Resuelve los enlaces simbólicos y funciona con /Foo/ o ~/foo.txt si no existen, pero no con /Foo/foo.txt si /Foo/ no existe.

$ brew install coreutils
$ greadlink -f /etc
/private/etc
$ greadlink -f ~/Documents/
/Users/lauri/Documents
$ greadlink -f ..
/Users
$ greadlink -f //etc/..////
/private
$ greadlink -f /Foo
/Foo
$ greadlink -f /Foo/foo.txt
$ 

Esto no resuelve los enlaces simbólicos, y no funciona con /Foo/foo.txt o bien.

abspath() {
  if [ -d "$1" ]; then
    ( cd "$1"; dirs -l +0 )
  else
    ( cd "$(dirname "$1")"; d=$(dirs -l +0); echo "${d%/}/${1##*/}" )
  fi
}

abspath /etc # /etc
abspath /Foo/foo.txt # doesn't work
abspath /Foo # works
abspath .
abspath ./
abspath ../
abspath ..
abspath /
abspath ~
abspath ~/
abspath ~/Documents
abspath /\"\ \'
abspath /etc/../etc/
abspath /private//etc/
abspath /private//
abspath //private # //private
abspath ./aa.txt
abspath aa.tar.gz
abspath .aa.txt
abspath /.DS_Store

dirs -l realiza la expansión de la tilde. dirs +0 imprime sólo el directorio superior si hay otros directorios en la pila. También podría reemplazar las subcarpetas con algo como old="$PWD" ... cd "$old" .

El expand_path de Ruby funciona con todas las rutas que no existen, pero no resuelve los enlaces simbólicos.

$ ruby -e 'print File.expand_path ARGV[0]' ~/aa/bb
/Users/lauri/aa/bb$

1voto

ironfroggy Puntos 3496

No estoy seguro de que esta respuesta sea lo suficientemente completa para tus necesidades, pero esto es lo que yo haría

--DISCLAIMER: No he probado esto en SH/BASH/Anything así que solo usa esto como un marco de trabajo por favor. Siéntete libre de editar la pregunta después de que lo hayas hecho funcionar.

Puede comprobar si el argumento script comienza con un carácter utilizando algo como if [[ $a == "/*" ]] .

Dado que todas las rutas relativas conllevan la suposición de que la ruta de trabajo es el directorio padre, si se sabe que la ruta es no ya absoluta se puede utilizar pwd , asumiendo que el script o el proceso padre no ha cambiado el directorio de trabajo .

Si el problema del cambio del directorio de trabajo es importante, tendrá que utilizar una función como find .


Algunos apuntes adicionales que podrían ponerte en el camino correcto para resolver tu problema: https://unix.stackexchange.com/questions/6435/how-to-check-if-pwd-is-a-subdirectory-of-a-given-path

http://www.unix.com/shell-programming-scripting/36200-getting-full-path-relative-path.html

https://stackoverflow.com/questions/2172352/in-bash-how-can-i-check-if-a-string-begins-with-some-value

Espero que esto te ponga en la dirección correcta.

1voto

Oskar Puntos 1242

No - una ruta es sólo una cadena y tienes que analizarla para decidir si es absoluta o relativa a $PWD o ~

Vea esto para obtener más contexto en caso de que mi respuesta sea demasiado corta.

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X