
私はTravis-CIでFindを使ってプログラムで特定のファイル形式をチェックしています。 (正確に言えばシェルチェックです。)
ただし、find
それによって実行されたコマンド/サブシェルの終了コードを使用すると、「メインスクリプト」に渡されず、自然に破棄されます。
たとえば、以下はfindコマンドです。
find . -type f -iname "*.sh" -exec sh ./testScripts.sh "{}" \;
./testScripts.sh
テスト結果に応じて、0または> = 1で終了することがあります。
正しい終了コードで正しく終了しますが、testScripts.sh
コマンドfind
の終了コードは常に「0」です。私が欲しいのはファイル/実行エラー、このエラーはTravis-CIに「伝播」されました。
どうすればいいですか?
答え1
コメントでStephen Kittの提案を使用してください。
find . -type f -iname "*.sh" -exec sh -c 'for n; do ./testScripts.sh "$n" || exit 1; done' sh {} +
これにより、sh -c
スクリプトはゼロ以外の終了状態でできるだけ早く終了しますtestScript.sh
。つまり、find
ゼロ以外の終了状態でも終了します。
プラス記号で終わると、デフォルトのパス名を評価するパス名はセットとして集計され、ユーティリティは同様にセットごとに1回呼び出されます
xargs(1)
。 ゼロ以外の終了状態で通話が終了すると、この操作find
も最終的に行われます。しかし、これは早期にfind
終了しません。
コメントの質問について:
for n; do ... ; done
奇妙に見えますが、繰り返すことができる項目がなく、for
ループが暗黙的に繰り返されることに気付くと理解できます"$@"
。sh
端の尾は$0
殻に配置されますsh -c
。{}
多くのパス名に置き換えられます。そこにない場合、sh
最初のパス名は終了し、$0
そこにないため、ループから選択されません$@
。$0
通常、現在のインタプリタの名前が含まれます(シェルによって生成されたエラーメッセージに使用されますsh -c
)。
答え2
xargs
xargs
コマンドが失敗すると、1から125(GNUの場合は123)の終了状態で終了し、コマンドが失敗して状態255で終了すると中断されます。
(with)の出力を安定して使用しxargs
、コマンドの標準入力を維持するにはGNUが必要です。したがって、GNUとプロセスの交換をサポートするシェルを使用してください。たとえば、次のようになります。find
-print0
xargs
xargs
ksh
zsh
bash
xargs -n1 -r0a <(find . -type f -iname '*.sh' -print0) sh ./testScripts.sh
または、最初の失敗時に中断します。
xargs -r0a <(find . -type f -iname '*.sh' -print0) sh -c '
for file do
sh ./testScripts.sh "$file" || exit 255
done' sh
find
(POSIXコード)を使用して、最初のエラーが発生したときに停止することもできます。
find . -type f -name '*.[sS][hH]' -exec sh -c '
for file do
if ! sh ./testScripts.sh "$file"; then
kill -s PIPE "$PPID"
exit 1
fi
done' sh {} +
(SIGPIPEを少なくしてください。騒々しい信号をエクスポートするには、一部のシェルを使用します(例bash
:)。これはfind
終了し、ゼロ以外の終了状態として返されます。
失敗したコマンド(ここでは最後)の終了ステータスの正確な値を取得するには、またはを使用して次のようにすることzsh
もbash
できます。
ret=0
while IFS= read -rd '' -u3 file; do
sh ./testScripts.sh "$file" 3<&- || ret=$?
done 3< <(find . -type f -iname '*.sh' -print0)
以下を使用しても、これを行うzsh
必要はありませんfind
。
set -o extendedglob
ret=0
for file (./**/*(#i).sh(D.)) {
./testScripts.sh $file || ret=$?
}