I have a shell script which checks for windows line endings.
set -e
(! git ls-files | xargs grep -I $'\r')
I am using the !
character to negate the return code of the command. Grep will return code 0
when a file with carriage return is found, and !
negates the value to the return code is then 1
and the script exits. When used with grep
(no xargs
) this works without parentheses. When xargs
is used the negation takes place according to $?
, as echo $?
will print 1
, however the script does not exit! After adding parentheses around the whole command, it works as expected. Why are the parentheses needed?
Bash brace expansion is used to generate stings at the command line or in a shell script. The syntax for brace expansion consists of either a sequence specification or a comma separated list of items inside curly braces "{}". A sequence consists of a starting and ending item separated by two periods "..".
Similar to the let command, the (( ... )) construct permits arithmetic expansion and evaluation. In its simplest form, a=$(( 5 + 3 )) would set a to 5 + 3, or 8.
[[ … ]] double brackets are an alternate form of conditional expressions in ksh/bash/zsh with a few additional features, for example you can write [[ -L $file && -f $file ]] to test if a file is a symbolic link to a regular file whereas single brackets require [ -L "$file" ] && [ -f "$file" ] .
Parentheses are often used for enclosing conditions and for function parameters. Braces are used for function bodies and objects. And brackets are used for lists or array notation. In Bash, that's often a little different and in many cases, parentheses, braces, and brackets act as commands themselves.
Your problem has nothing to do with xargs
.
The -e
option of bash is a little tricky.
-e Exit immediately if a pipeline (which may consist of a single simple command), a list, or a compound command , exits with a non-zero status. The shell does not exit if the command that fails is part of the command list immediately following a
while
oruntil
keyword, part of the test following theif
orelif
reserved words, part of any command executed in a&&
or||
list except the command following the final&&
or||
, any command in a pipeline but the last, or if the command's return value is being inverted with!
.
Let's look at a much simpler example:
$ 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
$
So, even though the exit status of "! true
" was non-zero, the script was allowed to run to the end and output the value of the exit status. That's because we didn't have any failing command - the non-zero exit code was due to deliberate negation.
However, if we enclose "! true
" in parentheses we introduce a failing (compound) command.
$ 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
$
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With