気づく:この投稿の元のタイトルでは、私は単語を使用しました。基準日常的な意味で「完璧」です(したがって、私が直接リリースできるクイックフィックスとは異なり、長い時間テストされています)。しかし、Unixの会話の文脈では、用語は基準非常に具体的で非常に異なる技術的意味を持っています。単語の別のより正確な解釈基準タイトルの内容が私の投稿の残りの部分と一致しないようにします。 (この点を指摘してくれたStéphane Chazelasに感謝します。)それでタイトルを修正しました。基準そしてテスト済みです。。
タイトルに記載されている質問の例として、次のようなディレクトリ構造があるとします。
/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
シンボリックリンクです。即時目標は一つです。比較的跡:
$ readlink /tmp/example/A/B/C/D/symlink-0
../../symlink-1/b/c/d/target
これに対応する絶対パスを取得したいと思います。即時ターゲット。 IOW、私は処刑したい部分の解決する
/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
次のことを意味します。いいえ私がここで尋ねる質問に対する答えです。
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
答え1
私はそのようなユーティリティを知りません。しかし、あなたのアプローチには欠陥があります。そして正しいアプローチが難しいことに同意します。
この:a
修飾子はファイルシステムにアクセスせずに絶対パスを計算します。特にシンボリックリンクかどうかに関係なくに変更されますa/b/..
。a
a/b
/a/b -> ../foo
シンボリックリンクがある場合は、シンボリックリンク自体ではない場合にのみ機能します/foo
。/a
正規化しても、シンボリックリンク自体のように$(dirname $1)
シンボリックリンクには適用されません。/a/b -> x/../../foo
x
あなたの場合:
/tmp/example/A/B/C/D/symlink-0 -> ../../symlink-1/b/c/d/target
シンボリックリンクもnではない/tmp/example/A/B/symlink-1/b/c/d/target
ので解決されます。/tmp/example/A/B/C/D
/tmp/example/A/B/C
つまり、..
コンポーネントなしでシンボリックリンクターゲットへの絶対パスを取得するには、複数のシンボリックリンクを解決する必要があり、ファイルパスとシンボリックリンクターゲットを組み合わせて単独で実行することはできません。
そのようなパスが必要な場合は、最も簡単な(合理的で有用であると言いたい)方法は次のとおりです。モデルシンボリックリンクターゲットへのパス、つまりすべてのパスコンポーネントは、シンボリックリンクも..
シンボリック.
リンクでもありません(最後のエントリを除く)。これを行うには、次の操作を行います。
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