John Freeman
John Freeman

Reputation: 2692

bash: exit if grep pipeline selects any lines

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

Answers (2)

Charles Duffy
Charles Duffy

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

hek2mgl
hek2mgl

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

Related Questions