この質問は、重要であればBashの文脈で最も適していますが、言語間の解決策を期待しています。
私が経験している問題は、あるスクリプトを別のスクリプトに「インポート」した場合に発生しますが、これを再帰的に実行することです。問題はこのことを無限にするようだということだ。
具体的なケースは次のとおりです。同じディレクトリに別のbashスクリプトをロードするための単純なbashスクリプトを作成しました。私のプロジェクトでは、すべてのスクリプトが同じディレクトリにあるので、今動作します。
したがって、「スクリプトローダー」は次のようになります(_source_script.sh
次の機能を定義するファイル)。
_source_script()
{
# Define a few colors for the possible error messages below.
RED=$(tput setaf 1)
NORMAL=$(tput sgr0)
EXPECTED_DIR="scripts"
if [ "$#" -ge "1" ]
then
EXPECTED_DIR=$1
fi
# Based on: http://stackoverflow.com/a/1371283/3924118
CURRENT_DIR=${PWD##*/}
if [ "$CURRENT_DIR" = "$EXPECTED_DIR" ]
then
for (( arg = 2; arg <= $#; arg++ ))
do
# Based on:
# - http://askubuntu.com/questions/306851/how-to-import-a-variable-from-a-script
# - http://unix.stackexchange.com/questions/114300/whats-the-meaning-of-a-dot-before-a-command-in-shell
# - http://stackoverflow.com/questions/20094271/bash-using-dot-or-source-calling-another-script-what-is-difference
printf ". ./${!arg}.sh\n"
# Try to load script ${!arg}.sh
. ./${!arg}.sh
# If it was not loaded successfully, exit with status 1.
if [ $? -ne 0 ]
then
printf "${RED}Script '${!arg}.sh' not loaded successfully. Exiting...${NORMAL}\n"
exit 1
fi
done
else
printf "No script loaded: $CURRENT_DIR != $EXPECTED_DIR.\n"
exit 1
fi
}
この「スクリプトローダー」を使用するには、まず次のように他のスクリプトから「インポート」する必要があります。
. ./_source_script.sh
問題は、関数を介して別のスクリプトを含めようとしたときです_source_script
。たとえば、スクリプトで以下を実行しようとすると、次のようになりますsome_script.sh
。
_source_script scripts colors asserts clean_environment
永久に実行され続けます。
内部にあるcolors.sh
:
#!/usr/bin/env bash
# Colors used when printing.
export GREEN=$(tput setaf 2)
export RED=$(tput setaf 1)
export NORMAL=$(tput sgr0)
export YELLOW=$(tput setaf 3)
内部にあるasserts.sh
:
...
. ./_source_script.sh
_source_script scripts colors
その中にclean_environment.sh
私はまた次のものがあります:
. ./_source_script.sh
_source_script scripts colors
私の理解によると、これは何もロードしないか、ループを探すスクリプトが見つかるまで再帰的に実行する必要がありますが、そうではありません。
だから私の解決策は次のとおりですsome_script.sh
。
_source_script scripts colors
_source_script scripts asserts
_source_script scripts clean_environment
つまり、個別に実行します。
それでは、ループで複数のスクリプトを「インポート」できないのはなぜですか?
ベストアンサー1
コードをあまり詳しく見ることなく、一般的なアプローチにはCの「ヘッダガード」に似たものが含まれます。
#ifndef HEADER_H
#define HEADER_H
/* The contents of the header file, with typedefs etc. */
#endif
このヘッダに関連するCプリプロセッサマクロはどこにHEADER_H
ありますか?ヘッダーがすでに含まれている場合は、ヘッダーを再度含めない場合にのみ使用されます。私は通常MCMC_H
、ヘッダーファイル自体から名前が派生したマクロを作成しますmcmc.h
。
シェルスクリプトでは、次のように簡単にできます。
if [ -z "$script_source_guard" ]; then
script_source_guard=1
# ... do things (define functions etc.)
fi
変数名はscript_source_guard
このファイルにのみ適用する必要があります。同様に、名前はソースファイル名から任意に派生できます。名前付きファイルには、myfuncts.shlib
名前付き保護変数があるか、別の名前を持つことができます。MYFUNCTS
_MYFUNCTS
guard_myfuncts