Short answer
Write
ps -ef | grep bar | { grep -v grep || test $? = 1; }
if you are using set -e.
If you use bash's pipefail option (set -o pipefail), remember to apply the exception handling (||test) to every grep in the pipeline:
ps -ef | { grep bar || test $? = 1; } | { grep -v grep || test $? = 1; }
In shell scripts I suggest you to use the ”catch-1-grep“ (c1grep) utility function:
c1grep() { grep "$@" || test $? = 1; }
Explained
grep's exit status is either 0, 1 or 2: [1]
0 means a line is selected
1 means no lines were selected
2 means an error occurred
grep can also return other codes if it's interrupted by a signal (e.g. 130 for SIGINT).
Since we only want to ignore exit status 1, we use test to suppress that specific exit status.
- If
grep returns 0, test is not run.
- If
grep returns 1, test is run and returns 0.
- If
grep returns any other value, test is run and returns 1.
In the last case, the script will exit immediately due to set -e or set -o pipefail. However, if you don't care about grep errors at all, you can of course write
ps -ef | grep bar | { grep -v grep || true; }
as suggested by Sean.
[additional] usage in shell scripts
In shell scripts, if you are using grep a lot, I suggest you to define an utility function:
# "catch exit status 1" grep wrapper
c1grep() { grep "$@" || test $? = 1; }
This way your pipe will get short & simple again, without losing the features of set -e and set -o pipefail:
ps -ef | c1grep bar | c1grep -v grep
FYI:
- I called it
c1grep to emphasize it's simply catching exit status 1, nothing else.
- I could have called the function
grep instead (grep() { env grep "$@" ...; }), but I prefer a less confusing and more explicit name, c1grep.
[additional] ps + grep
So if you want to know how to avoid grep -v grep or even the | grep part of ps|grep at all, take a look at some of the other answers; but this is somewhat off-topic imho.
[1] grep manpage