如何获取find启动的命令的退出码?

如何获取find启动的命令的退出码?

我在 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提前退出。


关于评论中的问题:

  1. for n; do ... ; done看起来很奇怪,但当您意识到没有任何可迭代的内容时,循环for将隐式迭代,这是有道理的"$@"

  2. sh末尾的尾部将被放置在 shell$0sh -c。将{}被许多路径名替代。如果没有sh那里,第一个路径名将以 结尾$0,并且不会被循环拾取,因为它不在$@.$0通常包含当前解释器的名称(它将在 shell 生成的错误消息中使用sh -c)。

答案2

xargsxargs如果任何命令失败,将以 1 到 125 之间的退出状态退出(GNU 为 123 ),如果任何命令失败并以 255 状态退出,则将中止。

为了可靠地使用(with )xargs的输出 并保留命令的标准输入,您需要 GNU 。因此,使用 GNU和支持进程替换的 shell,例如,或:find-print0xargsxargskshzshbash

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被杀死,并以非零退出状态返回。

要获取(此处为最后一个)失败命令的退出状态的确切值,使用zshbash,您还可以执行以下操作:

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=$?
}

相关内容