为什么我需要括号在bash`set -e`和否定返回码中

时间:2016-09-19 20:01:13

标签: linux bash shell xargs

我有一个shell脚本,用于检查Windows行结尾。

set -e
(! git ls-files | xargs grep -I $'\r')

我使用!字符来否定命令的返回码。当找到带回车符的文件时,Grep将返回代码0,然后!否定返回代码的值为1并退出脚本。与grep(无xargs)一起使用时,这不带括号。使用xargs时,根据$?进行否定,因为echo $?会打印1,但脚本不会退出!在整个命令周围添加括号后,它按预期工作。为什么需要括号?

2 个答案:

答案 0 :(得分:6)

您的问题与-e无关。

bash的while选项有点棘手。

  

-e 如果管道(可能包含             单个简单命令),列表复合命令             ,以非零退出             状态。 如果命令那么shell不会退出             failed是立即命令列表的一部分             遵循untilif关键字,是测试的一部分             遵循elif&&保留字,部分内容             除命令外,在||&&列表中执行的命令             在最后的||!之后,任何命令都在             管道但最后一个,或如果命令返回             价值与$ cat exit_on_error_test.sh #!/bin/bash trap 'echo Interrupted because of an error' ERR set -e ! true echo Exit status: $? $ ./exit_on_error_test.sh Exit status: 1 $ 相反。

让我们看一个更简单的例子:

! true

因此,即使“! true”的退出状态为非零,也允许脚本运行到结尾并输出退出状态的值。那是因为我们没有任何失败的命令 - 非零退出代码是由于故意否定。

但是,如果我们在括号中加上“$ cat exit_on_error_test.sh #!/bin/bash trap 'echo Interrupted because of an error' ERR set -e (! true) # This as a whole is now a failing (compound) command echo Exit status: $? $ ./exit_on_error_test.sh Interrupted because of an error $ ”,我们会引入一个失败的(复合)命令。

.container {
  display: flex;
  flex-flow: row wrap;
}

.header {
    min-height: 60px;
  border: 1px solid #000;
}

.list {
    height: 100%;
    display: flex;
    justify-content: flex-start;
    list-style: none;
    margin: 0;
    padding: 0;
}

li {
  padding: 10px;
  background-color: #cecece;
}

答案 1 :(得分:1)

set -e命令指示

  

如果命令以非零状态退出,则立即退出

(见help set)。

在Bash中,括号中的表达式创建subshell(子进程),其工作方式类似于单个命令。因此,如果子shell退出时出现错误代码,则父脚本也会退出(由于-e设置)。

因此,如果grep找到\r字符,则子shell以非零状态退出;主脚本也退出此代码(由于set -e)。

您的问题的答案为什么需要括号?是:因为您可能想要退出主脚本,如果grep在其中一个字符中找到\r字符git控制下的文件。