¿Cómo obtener la ruta relativa entre dos directorios?

¿Cómo obtener la ruta relativa entre dos directorios?

Digamos que tengo una variable con una ruta release/linux/x86y quiero la ruta relativa de un directorio diferente (es decir, ../../..del directorio de trabajo actual), ¿cómo puedo obtenerla en un comando de shell (o posiblemente en GNU Make)?

No se requiere soporte de enlace suave.


Esta pregunta se ha modificado en gran medida según la respuesta aceptada para mejorar la terminología.

Respuesta1

Absolutamente no está claro el propósito de esto, pero esto hará exactamente lo que se solicitó, usandoruta real de GNU:

realpath -m --relative-to=release/linux/x86 .
../../..
realpath -m --relative-to=release///./linux/./x86// .
../../..

Respuesta2

Aquí hay una función de shell que devuelve una ruta relativa desde el directorio de origen al de destino usando solo manipulación de cadenas, a través de la expansión de parámetros de shell, sin acceso al disco o a la red. Sin nombre de ruta resolución está hecho.

Espera dos parámetros, directorio-origen y directorio-destino, ambos nombres de ruta canonicalizados absolutos y no vacíos, cualquiera de los cuales puede terminar /en -, no es necesario que exista ninguno. Devuelve el resultado en la variable de shell $REPLYcomo una ruta relativa desde el directorio de origen al directorio de destino sin el final /, .si es nulo.

El algoritmo es de una publicación de comp.unix.shell de 2005 que ahora ha ascendido aarchivo.org.

pnrelpath() {
    set -- "${1%/}/" "${2%/}/" ''               ## '/'-end to avoid mismatch
    while [ "$1" ] && [ "$2" = "${2#"$1"}" ]    ## reduce $1 to shared path
    do  set -- "${1%/?*/}/"  "$2" "../$3"       ## source/.. target ../relpath
    done
    REPLY="${3}${2#"$1"}"                       ## build result
    # unless root chomp trailing '/', replace '' with '.'
    [ "${REPLY#/}" ] && REPLY="${REPLY%/}" || REPLY="${REPLY:-.}"
}

Usar como

$ pnrelpath "$HOME" "$PWD"
projects/incubator/nspreon
$ pnrelpath "$PWD" "$gimpkdir"
../../../.config/GIMP
$ pnrelpath "$PWD" "$(cd "$dirnm" && pwd || false)"
# using cd to resolve, canonicalize ${dirnm}

o conURIestamos compartiendo scheme://authority,

$ pnrelpath 'https://example.com/questions/123456/how-to' 'https://example.com/media'
../../../media

Actualizar2022-11-24

Omitir la whiledeclaración en la función anterior devolverá lo que realpath --relative-basehace: una ruta relativa desde el directorio de origen al directorio de destino si el destino está en el origen o debajo de él; de lo contrario, una ruta absoluta. Se aplican condiciones previas y posteriores similares.

pnrelbase() {
    set -- "${1%/}/" "${2%/}/"      ## '/'-end to avoid mismatch
    REPLY="${2#"$1"}"               ## build result
    # unless root chomp trailing '/', replace '' with '.'
    [ "${REPLY#/}" ] && REPLY="${REPLY%/}" || REPLY="${REPLY:-.}"
}

(finalizar actualización)

información relacionada