
ソースシェルスクリプトがその場所を知っていますか?私は読んだソースシェルスクリプトのパスの決定しかし、POSIXシェルを使用している場合、答えはbash
合計と失敗に焦点を当てます。tcsh
$0
また、解決策ではなく、誤った結果が発生します。。
ソリューションが100%信頼できる必要はありません。パスにハードリンクやシンボリックリンクが含まれる可能性はありません。
# sourcing the script should yield the absolute path to the script
. somedir/thescript
# within “thescript”
-> /tmp/foo/bar/somedir
いくつかの背景:bin
スクリプトは既存のアプリケーションの一部であり、ソーススクリプト(アーキテクチャによって異なります)に関連する既知の場所のディレクトリに数十のバイナリファイルが含まれています。アプリケーションを使用するには、ユーザーは、アプリケーションのバイナリを現在のシェル(どのシェルに関係なく)から簡単に呼び出すことができるように、スクリプトにディレクトリを追加する必要がありますbin
。PATH
答え1
POSIX仕様への拡張を提供するシェルを使用しないと、ソーススクリプトの場所を使用できません。次のコードスニペットを使用してテストできます。
env -i PATH=/usr/bin:/bin sh -c '. ./included.sh' | grep included
included.sh
含む
echo "$0"
set
bashでは、ソーススクリプトの名前はinです$BASH_SOURCE
。 zsh では (sh または ksh 互換モードではなく zsh 互換モードで) in です$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
シェルで開かれたファイルを見ると、スクリプトの場所を推測できます。実験的に、これはdashとpdkshでは動作しているように見えますが、bashまたはksh93では動作しないようです。 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`"
答え2
Gillesの答えに追加すると、これがどれほど正確かはわかりませんが、常にBusyBoxを使用してthis_scriptをif $0 = ash
指しているようです。/proc/$$ interface
/proc/$$/fd/11
(私のように)このページを閲覧している人に、潜在的な答えとしてこれを提供します。
最後の回答は削除されました。したがって、この作業に対する私の主張は、4つの異なるハードウェアプラットフォーム(x86、ARM、XLP、およびpowerpc)でテストされました。誰もが同じfd / 11の答えを提供します。読み取りリンクは/proc/$$/fd/11
私のスクリプトを生成します。
アンディ