299
255

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

bash/zshでsourceされたスクリプト内で、ファイル自身の絶対パスをとるシンプルな記法

Last updated at Posted at 2013-06-25
追記: コメント欄にて、若干変なパスが含まれている場合の対処方法について、補足いただきました。
ご指摘ありがとございますm(_ _)m

bash / zshなどでシェルスクリプトを書いていると、環境変数の設定を外部ファイルにまとめてsource して使う、というのはよくある。
そのような場合にsourceされたファイル内での絶対パスがイマイチうまく取れない、という問題に突き当たる事がある。

bashの話: うまくいかない方法と理由

通常、シェルスクリプト内で自分自身の絶対パスをとるときによくやるのが下記の手法だとおもう。

script_dir=$(cd $(dirname $0); pwd)

が、単体で呼び出した場合にはちゃんと動くのだが、bashからsourceで呼び出した場合にはうまく動かない。

なぜかというと、sourceされたファイルの実行が、呼び出し元のシェルプロセス内になるから。
bashでは$0は実行コンテキストに依らず、実行ファイル名が入っている。
そのため、source されたファイル内では$0が大本のファイルの情報となっているため、直感と異なる動きとなってしまう。

zshの話

ちなみに、zshだとちゃんと動く。zshは、$0をコンテキストに合わせて置き換える。
関数内であれば関数名になるし、sourceすればsourceされたファイルパスが入る。
そのため、zshなら$0を使っていれば問題ない。

bashの話: 解決の糸口

一般に言われるのは、$BASH_SOURCEを使う方法。
これには、呼び出されたファイル自身の絶対パスが入っている。そのため、bash限定であればこれを利用して

script_dir=$(cd $(dirname $BASH_SOURCE); pwd)

を使えば、解決できる。

これ使うと何が辛いか

bash限定なんですよね。zshかbashかを判定して、場合分けするような処理をいちいち書きたくない。

じゃあどうすんの

こうすればいい

script_dir=$(cd $(dirname ${BASH_SOURCE:-$0}); pwd)

$BASH_SOURCEが定義されていればそれを使い、無いなら$0を使う。
これでさくっと解決できる。

最後のほう書くの面倒になって説明が雑になった。。。わけじゃないよ!><

299
255
7

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
299
255

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?