2 つのディレクトリ間の相対パスを取得するにはどうすればよいですか?

2 つのディレクトリ間の相対パスを取得するにはどうすればよいですか?

たとえば、パスを持つ変数がありrelease/linux/x86、別のディレクトリ (つまり、../../..現在の作業ディレクトリ) からの相対パスが必要な場合、シェル コマンド (または GNU Make) でそれを取得するにはどうすればよいですか?

ソフトリンクのサポートは必要ありません。


この質問は、用語の改善のため、承認された回答に基づいて大幅に変更されました。

答え1

目的が全く分かりませんが、これはまさに求められていることを実行します。GNU リアルパス:

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

答え2

これは、ディスクやネットワークにアクセスせずに、シェルパラメータの拡張を通じて文字列操作のみを使用してソースディレクトリからターゲットディレクトリへの相対パスを返すシェル関数です。パス名はありません 解決 終わらせる。

2 つのパラメータ、source-dir と target-dir が必要です。どちらも絶対正規化された空でないパス名で、どちらかが - で終わる場合があり、どちらも存在する必要がありません。void の場合は、末尾の なしで、source-dir から target-dir への相対パスとして/結果をシェル変数に返します。$REPLY/.

アルゴリズムは2005年のcomp.unix.shellの投稿から引用したもので、現在はアーカイブ

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:-.}"
}

使用

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

または、URI共有scheme://authority

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

アップデート2022-11-24

while前の関数のステートメントをスキップすると、次のものが返されますrealpath --relative-base。ターゲットがソース内またはその下にある場合は、ソースからターゲット ディレクトリへの相対パスが返され、それ以外の場合は絶対パスが返されます。同様の事前条件と事後条件が適用されます。

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

(更新終了)

関連情報