Reputation: 2692
I want a grep pipeline to succeed if no lines are selected:
set -o errexit
echo foo | grep -v foo
# no output, pipeline returns 1, shell exits
! echo foo | grep -v foo
# no output, pipeline returns 1 reversed by !, shell continues
Similarly, I want the pipeline to fail (and the enclosing shell to exit, when errexit
is set) if any lines come out the end. The above approach does not work:
echo foo | grep -v bar
# output, pipeline returns 0, shell continues
! echo foo | grep -v bar
# output, ???, shell continues
! (echo foo | grep -v bar)
# output, ???, shell continues
I finally found a method, but it seems ugly, and I'm looking for a better way.
echo foo | grep -v bar | (! grep '.*')
# output, pipeline returns 1, shell exits
Any explanation of the behavior above would be appreciated as well.
Upvotes: 2
Views: 782
Reputation: 295687
set -e
, aka set -o errexit
, only handles unchecked commands; its intent is to prevent errors from going unnoticed, not to be an explicit flow control mechanism. It makes sense to check explicitly here, since it's a case you actively care about as opposed to an error that could happen as a surprise.
echo foo | grep -v bar && exit
More to the point, several of your commands make it explicit that you care about (and thus are presumably already manually handling) exit status -- thus setting the "checked" flag, making errexit
have no effect.
Running ! pipeline
, in particular, sets the checked
flag for the pipeline -- it means that you're explicitly doing something with its exit status, thus implying that automatic failure-case handling need not apply.
Upvotes: 4
Reputation: 158160
This is not a one-liner, but it works:
if echo foo | grep foo ; then
exit 1
fi
Meaning the shell exits with 1 if grep finds something. Also I don't think that set -e
or set -o errexit
should be used for logic, it should be used for what it is meant for, for stopping your script if an unexpected error occurs.
Upvotes: 1