LoginSignup
8
9

More than 5 years have passed since last update.

shell スクリプト自身の絶対パスや格納ディレクトリを求める(OS X でも)

Last updated at Posted at 2014-10-10

この話題はさんざん出尽くしている感もありますが、自分用にワンライナー的にコピペできるものを模索していたので、備忘的にメモを残します。ターゲットは 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")")"

ではまた。

8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9