![当一个命令在子命令中失败时失败](https://linux22.com/image/122876/%E5%BD%93%E4%B8%80%E4%B8%AA%E5%91%BD%E4%BB%A4%E5%9C%A8%E5%AD%90%E5%91%BD%E4%BB%A4%E4%B8%AD%E5%A4%B1%E8%B4%A5%E6%97%B6%E5%A4%B1%E8%B4%A5.png)
我想在目录列表中执行命令: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
到该行来发出命令。
请注意,如果提供的代码片段是更大脚本的一部分,这将完全退出脚本。您可能需要考虑将其重写为for
orwhile
循环,以便您可以使用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