ディレクトリ内のすべてのスクリプトを現在のシェルセッションにどのように含めることができますか?

ディレクトリ内のすべてのスクリプトを現在のシェルセッションにどのように含めることができますか?

いくつかのスクリプトファイルを含むディレクトリがあります。

/scripts
    api.sh
    time.sh
    certificate.sh
    docker.sh
    nginx.sh
    wifi.sh
    ...

このスクリプトはコマンドではありません。ただいくつかの機能が含まれているだけです。だから追加し/script$PATH実行することはできません。たとえば、api.sh次の内容があります。

function isApi()
{
   # body
}

function resetApi()
{
   # body
}

function testDatabase()
{
   # body
}

現在のセッションに含めてからその機能を呼び出す必要があります。

1つずつ含めると、. /scripts/x.shその機能を使用できます。

ただし、bashスクリプトを実行してloadScripts.shロードすると機能しません。

find /scripts -mindepth 1 |
while read scriptFile;
do
    echo $scriptFile
    source $scriptFile
done

現在のセッションにディレクトリ内のすべてのスクリプトをどのように含めることができますか?

答え1

のみ:

for script in scripts/*.sh; do
  . "$script"
done

特別な.sh組み込みは、シェルに提供されたファイルのコードを評価するように指示します。 cshにはsource同様のコマンドがあり、一部のシェルは両方のbashコマンドをサポートし、.時にはsource意味がわずかに異なります。

.また、/onを使用する必要があります。これにより、スクリプトを解釈するための新しいシェルが開始されるため、関数は呼び出しシェルではなく対応する一時シェルで定義されます。sourceloadScripts.sh./loadScripts.sh

たとえば、現在の作業ディレクトリでifを実行して、/に渡されたパスにaが含まれていることを確認します/。それ以外の場合は、そのパスを見つけることができます。.source. ./loadScripts.sh$PATH

そうすることは間違っていますfind... | while read...; do . ...; done。まず、上記のすべての理由によるものです。検索結果を繰り返すのはなぜ悪い習慣ですか?また、bashこのオプションが有効になっていない場合など、複数のシェルでループがサブシェルで実行されるため、ソースファイル内の関数はそのサブシェルでのみ定義されるためです。lastpipewhile

バージョン 4.4 以降を使用したいが、ファイルのリストを並べ替え、隠しファイルを含めないように注意するには、find次のようにします。findbash

while IFS= read -rd '' -u3 script; do
  . "$script"
done 3< <(LC_ALL=C find scripts/ -mindepth 1 -maxdepth 1 -name '*.sh' -type f -print0)

ここに追加します-type f(ファイルの種類を制限するには定期的な)使用を正当化するためfind

zsh代わりにを使用している場合は、bash次のことができます。

for script (scripts/*(ND.)) . $script

同等のファイルとして(.一般ファイルのみ、D隠しファイルを含む)

または:

for script (scripts/*(ND.)) emulate sh -c '. $script'

これらのスクリプトの構文がsh拡張.sh機能が提案したとおりです。


posix¹bashは、このオプションが有効かどうかに関して異なる動作をします。

関連情報