Wie erhält man den relativen Pfad zwischen zwei Verzeichnissen?

Wie erhält man den relativen Pfad zwischen zwei Verzeichnissen?

Angenommen, ich habe eine Variable mit einem Pfad release/linux/x86und möchte den relativen Pfad von einem anderen Verzeichnis (also ../../..dem aktuellen Arbeitsverzeichnis). Wie erhalte ich diesen in einem Shell-Befehl (oder möglicherweise mit GNU Make)?

Softlink-Unterstützung nicht erforderlich.


Diese Frage wurde auf der Grundlage der akzeptierten Antwort zur Verbesserung der Terminologie stark modifiziert.

Antwort1

Der Zweck ist absolut nicht klar, aber es wird genau das tun, was gefragt wurde, mitGNU Realpath:

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

Antwort2

Hier ist eine Shell-Funktion, die einen relativen Pfad vom Quell- zum Zielverzeichnis zurückgibt, indem sie nur String-Manipulationen verwendet - durch Shell-Parametererweiterung - ohne Festplatten- oder Netzzugriff. Kein Pfadname Auflösung erledigt.

Erwartet zwei Parameter, Quellverzeichnis und Zielverzeichnis, beides absolute kanonisierte, nicht leere Pfadnamen, die beide /mit - enden können und nicht unbedingt vorhanden sein müssen. Gibt das Ergebnis in der Shell-Variable $REPLYals relativen Pfad vom Quellverzeichnis zum Zielverzeichnis ohne abschließendes - zurück /, .wenn es nichtig ist.

Der Algorithmus stammt aus einem comp.unix.shell-Posting von 2005, das inzwischen aufgestiegen ist zuarchive.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:-.}"
}

Benutzen als

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

oder mitURIs teilen scheme://authority,

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

Aktualisieren24.11.2022

Wenn Sie die whileAnweisung in der vorherigen Funktion überspringen, wird Folgendes zurückgegeben realpath --relative-base: ein relativer Pfad vom Quell- zum Zielverzeichnis, wenn das Ziel in oder unter der Quelle liegt, andernfalls ein absoluter Pfad. Es gelten ähnliche Bedingungen vor und nach der Anweisung.

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

(Update Ende)

verwandte Informationen