シェルスクリプト(BASH限定ですが)、他の言語でもよく見られる__FILE__や__DIR__みたいなことをするにはどのようにすれば良いか、と考えてみた結果以下のようになった。小生のシェルスクリプトスキルが高くないので何ともだが上手く動いているようだ。もっと良いやり方があるかもしれない。クロスシェル対応できたらと思ったが、他のシェルスクリプトのスキルがほぼないので今後の課題とする。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
set -ue __FILE__() { resolve_link "${BASH_SOURCE[1]}" } __DIR__() { dirname "$(resolve_link "${BASH_SOURCE[1]}")" # 間違い 9/30 修正 } resolve_link() { local filepath="$1" local filename ( while [ "$filepath" != "" ]; do cd "$(dirname "$filepath")" filename="$(basename "$filepath")" filepath="$(readlink "$filename" ||:)" done echo "$(pwd -P)/$filename" ) } |
それぞれのsource先でBASH_SOURCE
変数を参照する方法でも良いが、シンボリックリンクの場合に絶対パスを取得できないので、一枚関数をかましている。resolve_link
の方法は参考リンクを参照させていただいた。readlink
で-f
オプションが使えない場合でも動く。
以下のようなファイル構成で試してみる。環境はMax OS X。
1 2 3 4 5 6 7 8 9 10 11 |
$ tree . ├── bar -> foo.sh ├── file.sh ├── foo.sh ├── hello -> hello.sh └── hello.sh 0 directories, 5 files $ pwd /tmp/sample |
foo.sh
1 2 3 4 5 6 7 8 9 |
#!/usr/bin/env bash source file.sh echo $BASH_SOURCE __FILE__ __DIR__ dirname "`__FILE__`" source hello |
hello.sh
1 2 3 4 |
#!/usr/bin/env bash echo "*** hello.sh ***" echo $BASH_SOURCE __FILE__ |
barの実行。__FILE__
でちゃんとbarの参照先foo.shの絶対パスが表示されているようだ。
1 2 3 4 5 6 7 8 |
$ ./bar ./bar /private/tmp/sample/foo.sh /private/tmp/sample /private/tmp/sample *** hello.sh *** hello /private/tmp/sample/hello.sh |
foo.shの実行。
1 2 3 4 5 6 7 8 |
$ ./foo.sh ./foo.sh /private/tmp/sample/foo.sh /private/tmp/sample /private/tmp/sample *** hello.sh *** hello /private/tmp/sample/hello.sh |
参考リンク
- http://qiita.com/yudoufu/items/48cb6fb71e5b498b2532
- http://qiita.com/edvakf@github/items/b8400f7dfe9210aadddd
コメント