ソースシェルスクリプトの場所を見つける

ソースシェルスクリプトの場所を見つける

ソースシェルスクリプトがその場所を知っていますか?私は読んだソースシェルスクリプトのパスの決定しかし、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スクリプトは既存のアプリケーションの一部であり、ソーススクリプト(アーキテクチャによって異なります)に関連する既知の場所のディレクトリに数十のバイナリファイルが含まれています。アプリケーションを使用するには、ユーザーは、アプリケーションのバイナリを現在のシェル(どのシェルに関係なく)から簡単に呼び出すことができるように、スクリプトにディレクトリを追加する必要がありますbinPATH

ベストアンサー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`"

おすすめ記事