POSIX仕様の拡張機能を提供するシェルを使用していない限り、ソーススクリプトの場所は利用できません。これは、次のスニペットでテストできます。
env -i PATH=/usr/bin:/bin sh -c '. ./included.sh' | grep included
どこincluded.sh
に
echo "$0"
set
bashでは、ソーススクリプトの名前はにあり$BASH_SOURCE
ます。zsh(shまたはksh互換モードではなく、zsh互換モード)では、それが含まれます$0
(関数で$0
は、代わりに関数名です)。pdkshおよびdashでは使用できません。ksh93では、このメソッドは解決策を明らかにしませんが、含まれているスクリプトへの絶対パスはとして利用できます${.sh.file}
。
bashまたはksh93またはzshが必要な場合は、このスニペットを使用できます。
if [ -n "$BASH_SOURCE" ]; then
this_script=$BASH_SOURCE
elif [ -n "$ZSH_VERSION" ]; then
setopt function_argzero
this_script=$0
elif eval '[[ -n ${.sh.file} ]]' 2>/dev/null; then
eval 'this_script=${.sh.file}'
else
echo 1>&2 "Unsupported shell. Please use bash, ksh93 or zsh."
exit 2
fi
シェルが開いているファイルを調べることにより、スクリプトの場所を推測することができます。実験的に、これはダッシュとpdkshでは機能するようですが、bashまたはksh93では機能しないようです。少なくとも短いスクリプトでは、スクリプトファイルを実行するまでにスクリプトファイルを閉じています。
open_file=$(lsof -F n -p $$ | sed -n '$s/^n//p')
if [ -n "$open_file" ]; then
# best guess: $open_file is this script
fi
リダイレクトを使用して実行されている複雑なスクリプト内でスクリプトが提供されている場合、スクリプトは記述子の番号が最も大きいファイルではない可能性があります。開いているファイルをループすることができます。とにかくこれが機能することは保証されていません。ソーススクリプトを特定する唯一の信頼できる方法は、bash、ksh93、またはzshを使用することです。
インターフェースを変更できる場合は、スクリプトを調達する代わりeval
に、呼び出し側で渡されるシェルスニペットをスクリプトに出力させます。これは、環境変数を設定するスクリプトが通常行うことです。それはあなたのスクリプトが呼び出し側のシェルとシェル構成の気まぐれに関係なく書かれることを可能にします。
#!/bin/sh
FOO_DIR=$(dirname -- "$0")
cat <<EOF
FOO_DIR='$(printf %s "$FOO_DIR" | sed "s/'/'\\''/g")'
PATH="\$PATH:$FOO_DIR/bin";
export FOO_DIR PATH
EOF
呼び出し元で: eval "`/path/to/setenv`"