この話題はさんざん出尽くしている感もありますが、自分用にワンライナー的にコピペできるものを模索していたので、備忘的にメモを残します。ターゲットは Bash です。
さて、まさるさんが「Bashシェルスクリプトで自分の絶対パスを取得 | #eight」において、readlink(1) の「-f, --canonicalize」オプションや「-e, --canonicalize-existing」オプションを使うと良いと言っているのでいきなり結論が出て話が終わってしまいそうなのですが、いかんせん Mac OS X の readlink(1) はショボくて「-f」「-e」オプションがありません。Python でも使えば簡単ですが、シェルで完結させたいですし、それでいて相対リンクにも対応させたいのです。さて困った。
仕方がないので、ショボい readlink(1) と dirname(1) を使いながらチマチマとリンクを辿って、本体が格納されているディレクトリを求めます。
path="$0"
while true
do
target="$(readlink "$path")"
cd "$(dirname "$path")"
if test -z "$target" # リンクが尽きたら終わり
then
break
fi
path="$target"
done
pwd --physical
"cd" せずに辿る方が正しいのでしょうが、煩雑になってしまいワンライナーにならなさそうなのでやめました。これを一行につぶすと、以下のような感じでしょうか。
p="$0";while true;do t="$(readlink "$p")";cd "$(dirname "$p")";test -z "$t"&&break||p="$t";done;pwd -P
これを用いて、「シンボリックリンクから実行されるスクリプトの本体が存在するディレクトリを $PATH に含める」ことで機能をサブコマンドへ分割したいのであれば、以下のような記述ができるかと思います(今回は、実際にはこれがやりたかった)。
export PATH="$(p="$0";while true;do t="$(readlink "$p")";cd "$(dirname "$p")";test -z "$t"&&break||p="$t";done;pwd -P)":"$PATH"
スクリプトファイルの絶対パスを求めるのであれば、以下のようになります。
self="$(p="$0";while true;do t="$(readlink "$p")";cd "$(dirname "$p")";test -z "$t"&&break||p="$t";done;echo "$(pwd -P)/$(basename "$p")")"
ではまた。