やりたいこと
例えば~/v1.0.0、~/v2.0.0…みたいに何らかのプログラムとか プロジェクトをバージョン毎に管理してたりするとき、 その中にsetup.shみたいなのを置いておいて、そのファイルの中で、
export PATH=~/v1.0.0/bin:$PATH
export LD_LIBRARY_PATH=~/v1.0.0/lib:$LD_LIBRARY_PATH
みたいな設定をしたいとします。
この様に直接PATHを書いてしまうと、新しいバージョンになった時に この設定ファイル自体も書き換えが必要です。
また、違う環境に持っていった時にPATHが変わってしまう可能性があります。
なので、通常は、この様な設定ファイルの中では
export PATH=$PROJECT_PATH/bin:$PATH
export LD_LIBRARY_PATH=$PROJECT_PATH/lib:$LD_LIBRARY_PATH
みたいにして、PROJECT_PATH
の様な別の環境変数を参照するようにして、
実際source
する際に、
$ export PROJECT_PATH=~/v1.0.0
$ source ~/v1.0.0/setup.sh
みたいにする方が素直に出来ます。
ですが、これだと1回余計な設定が必要になってしまいます。
source ~/v1.0.0/setup.sh
の時点でそのディレクトリを見てるわけなので
ファイルのなかで自動で自分のパスを取得して設定してほしいな、と。
BASH_SOURCE
以下、Bash 4.3.33でやっています。
Bashの通常のスクリプトだと、引数の0番目、$0
、にファイルへのパスが入っています。
1 2 |
|
これを実行すると(直接、またはbash
の引数として):
$ ./path.sh
./path.sh
$ bash ./path.sh
./path.sh
$ mkdir test && cd test
$ ../path.sh
../path.sh
$ cd ../
ただ、source
(または.
)すると
$ source path.sh
/usr/local/bin/bash
と、現在使ってるシェルが$0
に入っています。
これは
$ echo $0
/usr/local/bin/bash
となるように、現在のbash
のセッションの中でそのままコマンドが実行されてる
のと同じだとみなされるからです。
この様な場合は代わりにBASH_SOURCE
というシェル変数があって、
ここにsource
で呼び出されたファイルのパスが入っています。
1 2 3 |
|
とすると、
$ ./path2.sh
./path2.sh
./path2.sh
$ source ./path2.sh
/usr/local/bin/bash
./path2.sh
$ cd test
$ ../path2.sh
../path2.sh
../path2.sh
$ source ../path2.sh
/usr/local/bin/bash
../path2.sh
と言った感じにBASH_SOURCE
の方ではsource
した場合でもファイルのパスを取ってこれます。
これを使えば後は、
1 2 3 |
|
とでもしておけばOK。
"$(cd "$(dirname "$BASH_SOURCE")" && pwd)"
の部分はdirname
でファイルのあるディレクトリを取得、
その後一旦そのディレクトリに移動してpwd
をすることで
ファイルのあるディレクトリへの絶対パスを取得しています。
これでどこからsource ~/v1.0.0/setup.sh
をしても
PATHの値が
~/v1.0.0/bin:$PATH
になります。
また、同じファイルを~/v2.0.0/setup.shにおいておけば、
source ~/v2.0.0/setup.sh
をした場合、
~/v2.0.0/bin:$PATH
が設定されます。
Zshでは
使ったZshは5.0.5。
Zshではsource
をした場合は
${(%):-%N}
が${BASH_SOURCE}
と同じ役割をします1。
1 2 3 |
|
この様なスクリプトを作ってみると
$ ./path3.sh
./path3.sh
./path3.sh
$ source ./path3.sh
./path3.sh
./path3.sh
となり、この場合$0
でもsource
で取ってこれてる様に見えます。
ただし、これはオプションによっては使えない場合があって、
setopt nofunction_argzero
または
unsetopt function_argzero
の設定をしていると
$ setopt nofunction_argzero
$ ./path3.sh
./path3.sh
./path3.sh
$ source ./path3.sh
zsh
./path3.sh
と、source
した時にはzsh
という値が入ってしまいます。
${(%):-%N}
の方はファイルへのパスのまま。
同じ様なことが.zshrc
で設定した時にもオプションに関係なく起こります。
なので$0
ではなく${(%):-%N}
を使います。
従って、Zsh用のセットアップファイルであるならば
1 2 3 |
|
の様にしておけばOK。
Bash/Zsh両用
もし、Bash/Zsh両方で使いたければ
1 2 3 4 5 6 7 |
|
のようにわけるか、まとめて
1 2 3 |
|
の様に、BASH_SOURCE
を探して、無ければZsh用の変数を検索、
みたいにすることも出来ます。
-
man zshmisc
を見ると%N
はThe name of the script, sourced file, or shell function that zsh is currently executing, whichever was started most recently. If there is none, this is equivalent to the parameter $0. An inte- ger may follow the `%’ to specify a number of trailing path com- ponents to show; zero means the full path. A negative integer specifies leading components.
とのこと。