Este foro ya no está activo, así que no puedes publicar nuevas preguntas ni responder a las preguntas existentes.

¿Cómo convertir una ruta absoluta en relativa dentro de un script de bash?

2 de abril de 2011

Me gustaría convertir una ruta de archivo absoluta en relativa a partir de otra ruta absoluta dada. Algo así:

absoluta="/foo/bar"
origen="/foo/baz/foo"
 
# magia bash ...
 
relativa="../../bar"

¿Alguien sabe cómo crear esa magia bash para que el script convierta las rutas absolutas en relativas?

Estás leyendo una traducción autorizada de la pregunta BASH: Convert absolute path into relative path given a current directory planteada por Paul Tarjan en StackOverflow.

Respuestas

#1

Si pudieras utilizar cualquier lenguaje de programación tipo Perl/Python/PHP/Ruby, podrías solucionar este problema fácilmente en una línea de código. Pero como pides solucionarlo mediante un script de Bash, esta es el código completo que debes utilizar:

# $1 y $2 deben ser rutas absolutas que empiecen por /
# el script devuelve la ruta relativa a $2/$target desde $1/$source
source=$1
target=$2
 
common_part=$source # for now
result="" # for now
 
while [[ "${target#$common_part}" == "${target}" ]]; do
    # no match, means that candidate common part is not correct
    # go up one level (reduce common part)
    common_part="$(dirname $common_part)"
    # and record that we went back, with correct / handling
    if [[ -z $result ]]; then
        result=".."
    else
        result="../$result"
    fi
done
 
if [[ $common_part == "/" ]]; then
    # special case for root (no common path)
    result="$result/"
fi
 
# since we now have identified the common part,
# compute the non-common part
forward_part="${target#$common_part}"
 
# and now stick all parts together
if [[ -n $result ]] && [[ -n $forward_part ]]; then
    result="$result$forward_part"
elif [[ -n $forward_part ]]; then
    # extra slash removal
    result="${forward_part:1}"
fi
 
echo $result

Y este sería el resultado de ejecutar este script con diferentes rutas:

$ calcula_ruta.sh "/A/B/C" "/A"           -->  "../.."
$ calcula_ruta.sh "/A/B/C" "/A/B"         -->  ".."
$ calcula_ruta.sh "/A/B/C" "/A/B/C"       -->  ""
$ calcula_ruta.sh "/A/B/C" "/A/B/C/D"     -->  "D"
$ calcula_ruta.sh "/A/B/C" "/A/B/C/D/E"   -->  "D/E"
$ calcula_ruta.sh "/A/B/C" "/A/B/D"       -->  "../D"
$ calcula_ruta.sh "/A/B/C" "/A/B/D/E"     -->  "../D/E"
$ calcula_ruta.sh "/A/B/C" "/A/D"         -->  "../../D"
$ calcula_ruta.sh "/A/B/C" "/A/D/E"       -->  "../../D/E"
$ calcula_ruta.sh "/A/B/C" "/D/E/F"       -->  "../../../D/E/F"

@librosweb

9 octubre 2014, 18:00