Short answer
To write
ps -ef | grep bar | { grep -v grep || test $? = 1; }
if you use set -e .
If you use pipefail bash pipefail ( set -o pipefail ), be sure to apply exception handling ( ||test ) to each grep in the pipeline:
ps -ef | { grep bar || test $? = 1; } | { grep -v grep || test $? = 1; }
In shell scripts, I suggest you use the catch-1-grep (c1grep) utility function:
c1grep() { grep "$@" || test $? = 1; }
Explanation
grep output status: 0, 1 or 2: [1]
0 means the line is selected1 means no row was selected2 means an error has occurred
grep may also return other codes if it was interrupted by a signal (for example, 130 for SIGINT).
Since we want to ignore only the state of output 1 , we use test to suppress this specific state of output.
- If
grep returns 0 , test does not start. - If
grep returns 1 , test is executed and returns 0 . - If
grep returns any other value, test is executed and returns 1 .
In the latter case, the script will immediately terminate due to set -e or set -o pipefail . However, if you do not care about grep errors, you can write
ps -ef | grep bar | { grep -v grep || true; }
as suggested by Sean .
[optional] shell script usage
In shell scripts, if you often use grep , I suggest you define a utility function:
# "catch exit status 1" grep wrapper c1grep() { grep "$@" || test $? = 1; }
Thus, your pipe will again become short and simple without losing the set -e and set -o pipefail functions:
ps -ef | c1grep bar | c1grep -v grep
FYI:
- I called it
c1grep to emphasize that it is just c1grep state of output 1 , nothing more. - I could instead call the
grep ( grep() { env grep "$@"...; } ) function, but I prefer the less confusing and more explicit name c1grep .
[1] grep manpage
myrdd Apr 03 '18 at 10:39 2018-04-03 10:39
source share