ディレクトリごとに環境変数を切り替えたいというユースケースはよくありますが、それを実現してくれるのが direnv です。
ぼくもこの direnv を利用して、AWS アカウントごとのアクセスキーを切り替えたりしています。
direnv は通常、各シェルの cd の実行をフックする形で動きます。しかし、シェルスクリプトの中でこれを実現できない。どうやるものかと思っていたら、最終的には direnv export ${SHELL} を呼び出せば良いということに気付きました。
direnv のセットアップは eval $(direnv hook ${SHELL}) で実行します。direnv hook zsh の出力をみてみましょう。
$ direnv version
2.22.0
$ direnv hook zsh
_direnv_hook() {
trap -- '' SIGINT;
eval "$("/usr/local/bin/direnv" export zsh)";
trap - SIGINT;
}
typeset -ag precmd_functions;
if [[ -z ${precmd_functions[(r)_direnv_hook]} ]]; then
precmd_functions=( _direnv_hook ${precmd_functions[@]} )
fi
typeset -ag chpwd_functions;
if [[ -z ${chpwd_functions[(r)_direnv_hook]} ]]; then
chpwd_functions=( _direnv_hook ${chpwd_functions[@]} )
fi
precmd_functions が出てきますが、これはプロンプト表示前を hook して実行される zsh の function 配列です。
このため、zsh だと _direnv_hook をディレクトリ変更都度に実行していることがわかります。
さらに、本質的な処理は /usr/local/bin/direnv export zsh のみであることもわかります。
結果として、シェルスクリプトで cd する際、cd の場合に以下のような function を実行すれば良いです。
function direnv_cd() {
cd "$1"
eval "$(direnv export bash)"
}
direnv_cd /path/to/destDir