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)が必要で、両方とも完全に正規化された空でないパス名です。どちらも/- で終わることができ、どちらも存在する必要はありません。空の場合、結果は後続することなく$REPLYソースディレクトリからターゲットディレクトリへの相対パスとしてシェル変数に返されます。/.

2005年のcomp.unix.shell投稿のアルゴリズムが次に更新されました。Archive.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:-.}"
}

使用

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

または統一リソース識別子分割する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:-.}"
}

(アップデート終了)

関連情報