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