我在 Travis-CI 中使用“查找”来通过程序检查特定文件类型。 (准确的说,是shellcheck检查。)
但是,当使用find
由其执行的命令/子 shell 的退出代码时,它们自然会被丢弃,因为它们不会传递给“主脚本”。
作为示例,这是一个查找命令:
find . -type f -iname "*.sh" -exec sh ./testScripts.sh "{}" \;
./testScripts.sh
可能会以 0 或 >= 1 退出,具体取决于测试结果。
使用正确的退出代码正确退出testScripts.sh
,但由于find
命令的退出代码始终为“0”。我想要的只是如果一个文件/执行错误,此错误被“传播”到 Travis-CI。
我怎样才能做到这一点?
答案1
使用斯蒂芬·基特在评论中的建议:
find . -type f -iname "*.sh" -exec sh -c 'for n; do ./testScripts.sh "$n" || exit 1; done' sh {} +
这将导致sh -c
脚本尽快以非零退出状态退出testScript.sh
。这意味着find
也将以非零退出状态退出:
如果以加号终止,则评估主路径名的路径名将聚合到集合中,并且每个集合将调用实用程序一次,类似于
xargs(1)
. 如果任何调用以非零退出状态退出,那么find
最终也会这样做,但这不会导致find
提前退出。
关于评论中的问题:
for n; do ... ; done
看起来很奇怪,但当您意识到没有任何可迭代的内容时,循环for
将隐式迭代,这是有道理的"$@"
。sh
末尾的尾部将被放置在 shell$0
中sh -c
。将{}
被许多路径名替代。如果没有sh
那里,第一个路径名将以 结尾$0
,并且不会被循环拾取,因为它不在$@
.$0
通常包含当前解释器的名称(它将在 shell 生成的错误消息中使用sh -c
)。
答案2
xargs
xargs
如果任何命令失败,将以 1 到 125 之间的退出状态退出(GNU 为 123 ),如果任何命令失败并以 255 状态退出,则将中止。
为了可靠地使用(with )xargs
的输出 并保留命令的标准输入,您需要 GNU 。因此,使用 GNU和支持进程替换的 shell,例如,或: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 作为 less嘈杂用一些 shell 发出信号,例如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=$?
}