当一个命令在子命令中失败时失败

当一个命令在子命令中失败时失败

我想在目录列表中执行命令:gradle --build-cache。此外,该目录需要以字符串“Project”开头,而不是以“Test”结尾。我使用以下命令成功做到了这一点:

find . -maxdepth 1 -type d \( ! -name . \) -name "Project*" ! -name "*Test*" -exec sh -c "cd '{}' && pwd && gradle --build-cache" \;

但我的问题是 gradle 命令可能会失败。如果我单独启动该命令,它会返回“exit 1”,但如果其中一个目录命令失败,它不会返回失败并且脚本会继续。最后,循环返回成功exit 0...

当 gradle 命令失败时如何停止循环执行并返回通用命令 an exit 1

谢谢 :)

答案1

这是一个类似的问题https://apple.stackexchange.com/questions/49042/how-do-i-make-find-fail-if-exec-fails。我列举了两种最有可能实现目标的有用方法。

最简单的方法是使用xargs,但是只有当命令可以找到的任何路径中没有空格时,这才有效find

find … -print0 | xargs -0 -n1 invalid_command

如果您坚持使用较旧的 Bash(低于 4.xx),您还可以摆脱 find 并使用递归通配符,或者自行实现递归搜索(我怀疑您的目录树是否足够深以引起问题)。

shopt -s globstar
set -e
for x in **/*.xml; do invalid_command "$x"; done

另外,如果您不需要它成为单行,您可以首先找到所有目录,将它们保存到临时文件(用于mktemp该文件),然后对列表执行您需要的任何操作。进一步过滤它,对它们运行命令......

答案2

您可以测试最后一个命令是否因错误退出,然后exit通过附加if [[ $? != 0 ]] ; then exit ; fi到该行来发出命令。

请注意,如果提供的代码片段是更大脚本的一部分,这将完全退出脚本。您可能需要考虑将其重写为fororwhile循环,以便您可以使用break

答案3

只是为了好玩,这里有一个find-only 答案。我认为您不能仅使用 的 POSIX 功能来做到这一点find,但由于您已经使用了一些 GNUism,因此您可以利用该-quit原语:

$ find -exec command {} \; -o -quit

这使得find一旦command失败就立即退出(即返回非零退出代码)。现在,要强制find以非零状态退出,您需要让它执行一些在-quit.一种方法是

$ find -exec command {} \; -o -fprint /dev/full -quit

因为所有写入/dev/full都会失败。您将收到一条错误消息,例如

find: ‘/dev/full’: No space left on device

2>/dev/null如果需要,您可以将其过滤掉。

如果您正在使用NetBSD 查找,你可以这样做:

$ find -exec command {} \; -o -exit 1

相关内容