NB:この投稿の元のタイトルでは、「定評のある」という日常的な意味で、Wordstandardを使用しました。 (したがって、迅速な解決策とは対照的に、私は自分自身を転がすことができました)。ただし、Unixトークのコンテキストでは、Wordstandardには非常に具体的な(そして非常に異なる)技術的な意味があります。タイトルのWordstandardのこの代替の、より正確な解釈は、私の投稿の残りの部分に一貫性を持たせませんでした。 (これを指摘してくれたStéphaneChazelasに感謝します。)したがって、タイトルを改訂し、standardをに置き換えました。テスト済み。
タイトルで言及している問題の例として、以下に示すディレクトリ構造があるとします。
/tmp/example
├── a/
│ └── b/
│ └── c/
│ └── d/
│ └── target
└── A/
└── B/
├── C/
│ └── D/
│ └── symlink-0 -> ../../symlink-1/b/c/d/target
│
└── symlink-1 -> /tmp/example/a
ご了承ください /tmp/example/A/B/C/D/symlink-0
は、immediateターゲットがrelativeパスであるシンボリックリンクです。
$ readlink /tmp/example/A/B/C/D/symlink-0
../../symlink-1/b/c/d/target
このimmediateターゲットに対応する絶対パスを取得したいと思います。 IOW、partial解決を実行したい
/tmp/example/A/B/C/D/symlink-0 -> /tmp/example/A/B/symlink-1/b/c/d/target
これを行うための標準的な(または少なくとも十分に確立され、実績のある)Unixユーティリティはありますか?
ご了承ください readlink -f
パスを完全に(シンボリックリンクのないパスに)解決します。ここで説明するケースの場合、たとえば、次のようになります。
$ readlink -f /tmp/example/A/B/C/D/symlink-0
/tmp/example/a/b/c/d/target
この意味は readlink -f
はnot私がここで尋ねている質問への答えです。
次のzsh
関数のようなものに適切なエラーチェックなどを追加することで、自分でロールすることができます。
canonicalize () {
local abspath=$(dirname $1)/$(readlink $1)
printf -- '%s\n' $abspath:a
}
...しかし、この種のユーティリティを堅牢に実装することの難しさを過小評価しないように(難しい方法で)学んだので、可能であれば既存のツールを使用したいと思います。
FWIW、以下のスクリプトはこの投稿の例を生成します:
mkdir -p /tmp/example/a/b/c/d /tmp/example/A/B/C/D
touch /tmp/example/a/b/c/d/target
ln -s /tmp/example/a /tmp/example/A/B/symlink-1
ln -s ../../symlink-1/b/c/d/target /tmp/example/A/B/C/D/symlink-0
私はそのようなユーティリティを知りません。しかし、あなたのアプローチには欠陥があります(そして私はそれを正しくするのが非常に難しいことに同意します)。
_:a
_修飾子は、ファイルシステムにアクセスせずに絶対パスを計算します。特に、_a/b/..
_がシンボリックリンクであるかどうかに関係なく、_a/b
_をa
に変更します。
_/a/b -> ../foo
_シンボリックリンクがある場合、それは_/foo
_がシンボリックリンク自体でない場合にのみ_/a
_です。 $(dirname $1)
を正規化しても、x
自体がシンボリックリンクである場合、_/a/b -> x/../../foo
_のようなシンボリックリンクでは機能しません。
あなたの場合:
_/tmp/example/A/B/C/D/symlink-0 -> ../../symlink-1/b/c/d/target
_
_/tmp/example/A/B/symlink-1/b/c/d/target
_も_/tmp/example/A/B/C/D
_もシンボリックリンクではないため、_/tmp/example/A/B/C
_に解決されます。
つまり、_..
_コンポーネントを含まないシンボリックリンクのターゲットへの絶対パスを取得するには、複数のシンボリックリンクを解決する必要があり、ファイルのパスとシンボリックリンクのターゲット。
このようなパスが必要な場合、最も簡単な(そして合理的および/または有用な)アプローチは、シンボリックリンクのターゲットのcanonicalパスを取得することです。これは、すべてのパスコンポーネントが存在する場所です。 _..
_、_.
_でも、シンボリックリンクでもありません。そのために、あなたはすることができます:
_zmodload -F zsh/stat b:zstat
canonicalize1() {
if [ -L "$1" ]; then
local link
zstat -A link +link -- "$1" || return
case $link in
(/*) ;;
(*)
case $1:h in
(*/) link=$1:h$link;;
(*) link=$1:h/$link;;
esac;;
esac
printf '%s\n' $link:h:A/$link:t
else
printf '%s\n' $1:A
fi
}
_
_/tmp/example/A/B/C/D/symlink-0
_シンボリックリンクでは、シンボリックリンクのターゲットがシンボリックリンクではないため、それでも_/tmp/example/a/b/c/d/target
_が得られますが、それが目的でない場合は、次のように質問します。 :
_canonicalize1 /tmp/x/y
_
_/tmp/x/y
_が_../foo
_へのシンボリックリンクであり、_/tmp/x
_が_/a/b/c
_および_/a
_へのシンボリックリンクである場合、_/a/b
_、_/a/b/c
_もそれ自体です。シンボリックリンク?