*.shを使用して異なるディレクトリにある複数の.shファイルを実行する方法

*.shを使用して異なるディレクトリにある複数の.shファイルを実行する方法

.shディレクトリパターン内のすべてのファイルを実行できるシェルスクリプトを作成する必要があります。それは次のとおりです。

##!/bin/bash
sh /var/scripts/*/my_*.inc.sh

ただし、上記のスクリプトは1つのファイルのみを実行します。最初に発生したファイル(最後の変更日によって選択されたように見えます)は私のポイントではありません。ルールに一致するすべてのファイルを実行する必要があります。

答え1

コードが機能しないのは、ファイル名のワイルドカードパターンが拡張されたときに発生するためです。

このモデルは次に拡張されます。リスト一致するパス名。スクリプトのコードはshこのリストを使用して呼び出します。これは、最初に一致する名前をスクリプトとして実行し、他の名前を次のように指定することを意味します。議論このスクリプトでは:

sh /var/scripts/dir/my_first.inc.sh /var/scripts/dir/my_second.inc.sh /var/scripts/dir/my_third.inc.sh

代わりに、一致する名前を繰り返すだけです。

#!/bin/sh

for name in /var/scripts/*/my_*.inc.sh; do
    sh "$name"
done

shこれは、一致する各名前が実行される必要がある(ない)スクリプトであると仮定しますbash。そのファイルが実行可能で正しい行を持っている場合は、上記のループのスクリプト呼び出しからそのファイルを削除してください#!shファイルが「ドットスクリプト」、つまりソースを提供する必要があるスクリプトである場合は、スクリプトが現在のスクリプトのコンテキストで実行されるようにするには、次のようにsh置き換えます。.

上記のスクリプトはどの機能も使用しないため、shscript()にすることができます。他のスクリプトが「ドットスクリプト」の場合、スクリプトを取得するには明らかに変更する必要があるか、別のインタプリタが必要な場合があります。#!/bin/shbash#!/bin/bash

答え2

拡張子は、.inc.shこれらの.inc.shファイルが次のようになることを示します。含むつまり、その内容はシェルコードで評価する必要があります。一つ同じシェルインタプリタを使用できるようにするシェルインタプリタ機能変わりやすいニックネーム...利用可能なファイルで定義されています。

bash彼らのsh文法bashshshshbash

bash(POSIXモードでない場合)との間の重要な違いの1つは、スクリプトが拡張をサポートしていないことshです。ただし、これはオプションまたはオプションを設定することで解決できるため、次のようにできます。bashaliasexpand_aliasesposix

#! /bin/bash -
set -o posix # increase POSIX sh compatibility, some but not all bash-specific
             # extensions are still available.

for file in /var/scripts/*/my_*.inc.sh; do
  . "$file"
done

# rest of the code that uses the functions/variables, etc defined
# in the files sourced above with the "." special builtin

一致するファイルがない場合は、文字通り.存在しないファイルをインポートしてシェルを終了しようとすると、/var/scripts/*/my_*.inc.shコマンドは失敗します。

この場合、何もしたくない場合は、次のことができます。

shopt -s nullglob
files=(/var/scripts/*/my_*.inc.sh)
shopt -u nullglob

for file in "${files[@]}"; do
  command . "$file"
done

を使用すると、nullglob一致しない glob が非拡張パターンではなく空のリストに展開されます。接頭辞を使用すると、command特殊な組み込み関数が失敗したため.(たとえば、$file読み取れない場合など)、シェルは終了しません(エラーを報告し続ける必要があります)。

.inc.shサブディレクトリの代わりにファイルを繰り返し検索するには、/var/scriptsこのオプションを使用して演算子をglobstar有効にできます。**

shopt -s nullglob globstar
files=(/var/scripts/**/my_*.inc.sh)
shopt -u nullglob globstar

.いずれにせよ、名前が(hidden)で始まるディレクトリとファイルは省略されます。dotglob以下を含めるには、このオプションを使用します。

明らかに、ソーススクリプトが失敗内で呼び出された場合、構文エラーがある場合、または特殊な組み込み関数が呼び出された場合、スクリプトもexit終了execします。

答え3

シェルスクリプト(bashを含む)でファイルを繰り返す最も安全な方法は、forループでパス名拡張(ワイルドカード)を使用することです。正しいコードは次のとおりです。

for file in /var/scripts/*/my_*.inc.sh
do
  echo "Executing $file"
  "$file"
done

スペース、アスタリスク、改行などの特殊文字を含むパスとファイル名を処理します。

再帰検索が必要な場合、またはglobbingで使用できないオプションを使用したい場合は、-execこのオプションと一緒にfindを使用できます(次は最近のGNU検索を想定しています)。

find a/ -executable -type f -name '*.sh' -exec {} \;

findがまだ必要ですが、各ファイルで複数のコマンドを実行したい場合はそれをread使用できますが、すべてのファイル名のオプションに注意する必要があります(次はbashとGNU findを想定しています)。

#!/bin/bash
find a/ -executable -type f -name '*.sh' -print0 |
  while IFS= read -r -d $'\0' file
  do
    echo "Executing $file"
    "$file"
  done

答え4

次のように forループを(再帰的に)使用して、見つかったパス内のすべてのシェルファイルを繰り返すことができます。find

for i in $(find /var/scripts/ -type f -name '*.sh')
  do sh "$i"
done

関連情報