Using set -e and grep to Prevent Premature Exit in Shell Scripts

bashcoreutilsgnugrep

Help required – in the context of shell scripting on a GNU/LINUX bash:

I always use set -e. Often, I would like to grep and do not always want the script to terminate execution if grep has an exit status of 1 indicating pattern not found.

Somethings I have tried to solve this problem are as follows:

(Try I)
If set +o pipefail and invoke grep with something like grep 'p' | wc -l then I get the desired behaviour until a future maintainer enables pipefail. Also, I like enabling pipefail so this does not work for me.

(Try II)
Use a sed or awk and only print lines matching pattern, then wc matched lines to test for matched pattern. I don't like this option because using sed to grep seems like a workaround for my true problem.

(Try III)
This one is my least favorite – something like: set +e; grep 'p'; set-e

Any insight/idioms would be most appreciated – thank you.

Best Answer

You can put the grep in an if condition, or if you don't care about the exit status, add || true.

Example: grep kills the shell

$ bash
$ set -e
$ echo $$
33913
$ grep foo /etc/motd
$ echo $$
9233

solution 1: throw away the non-zero exit status

$ bash
$ set -e
$ echo $$
34074
$ grep foo /etc/motd || true
$ echo $$
34074

solution 2: explicitly test the exit status

$ if ! grep foo /etc/motd; then echo not found; fi
not found
$ echo $$
34074

From the bash man page discussing set -e:

The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test following the if or elif 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 !.

Related Question