ある日同僚がこんなことを言っていた。
「ねえ @ma2saka さん。シェルスクリプトを強制的に bash で起動するにはどうしたらいいだろう。
ちょっと bash に依存したスクリプトを書きたいんだけど、shで実行されたら嫌なんだよね」
で、帰りの電車で考えていたわけです。
コメントで指摘もらった方式
昨晩考えていた方法はだいぶ的外れだったようです。コメントで指摘もらいました。
if [ -z "$BASH_VERSION" ] || [ "${BASH##*/}" != "bash" ]; then
echo "$0: ERROR: Use bash" >&2
exit 1
fi
echo "foo bar com"
簡潔ですね。
環境変数とシェル変数
$BASH_VERSION
と$BASH
は環境変数ではなくシェル変数です。
Shell Variables
The following variables are set by the shell:
http://codezine.jp/unixdic/w/シェル変数と環境変数 (CodeZine) によれば、
シェル変数は、現在実行しているシェルの中だけで有効な変数であり、環境変数は、新たなシェルを起動したり、コマンドを実行した場合にも継承される変数です。
ということで、シェル変数はサブシェルとか内部で実行しているコマンドには引き継がれません。(明示的に設定すれば環境変数として振る舞います)
最初、シェル変数の概念をすっかり忘れていて「BASH_VERSIONとか見ようとしても、親から引き継がれちゃうからなぁ」と悩んでいました。不覚です。
誰かに貸したまま帰ってこない入門bashを読み直さなければ…。
以下、蛇足ですが当初考えていた方法
detect.sh
# !/bin/bash
# tcsh , csh
which builtins | grep 'built-in command'>/dev/null && echo "maybe tcsh..">/dev/stdout && exit 1
# zsh
which comparguments 2>/dev/null | grep 'built-in command' > /dev/null && echo "maybe zsh" && exit 1
# sh
/usr/bin/type source 2>&1 | grep 'shell builtin' > /dev/null
if [ ! "$?" -eq "0" ] ;then
echo "maybe /bin/sh"
exit 1
fi
# posix on
set -o | grep posix | grep on > /dev/null && echo "maybe enable posix mode" && exit 1
echo "----------------------"
echo "hello bash!!!"
echo "----------------------"
実行結果
以下のようになりました。ひとまず期待通り…。
[tmp]$ csh detect.sh
maybe tcsh..
[tmp]$ tcsh detect.sh
maybe tcsh..
[tmp]$ zsh detect.sh
maybe zsh
[tmp]$ sh detect.sh
maybe enable posix mode
[tmp]$ bash detect.sh
----------------------
hello bash!!!
----------------------