Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
All of my scripts have errexit turned on; that is, I run
set -o errexit
. However, sometimes I want to run commands like
grep
, but want to continue execution of my script even if the command fails.
How do I do this? That is, how can I get the exit code of a command into a variable without killing my whole script?
I could turn errexit off, but I'd prefer not to.
–
–
–
–
Your
errexit
will only cause the script to terminate if the command that fails is "untested". Per
man sh
on FreeBSD:
Exit immediately if any untested command fails in non-interactive
mode. The exit status of a command is considered to be explic-
itly tested if the command is part of the list used to control an
if, elif, while, or until; if the command is the left hand oper-
and of an ``&&'' or ``||'' operator; or if the command is a pipe-
line preceded by the ! keyword.
So .. if you were thinking of using a construct like this:
grep -q something /path/to/somefile
retval=$?
if [ $retval -eq 0 ]; then
do_something # found
do_something_else # not found
you should instead use a construct like this:
if grep -q something /path/to/somefile; then
do_something # found
do_something_else # not found
The existence of the if keyword makes the grep command tested, thus unaffected by errexit. And this way takes less typing.
Of course, if you REALLY need the exit value in a variable, there's nothing stopping you from using $?:
if grep -q something /path/to/somefile; then
do_something # found
unnecessary=$?
do_something $unnecessary # not found
–
Here's a way to achieve this: you can "turn off" set -o errexit for some lines of code, and then turn it on again when you decide:
set +e #disables set -o errexit
grep -i something file.txt
rc="$?" #capturing the return code for last command
set -e #reenables set -o errexit
Another option would be the following:
grep -i something file.txt || rc="$?"
That would allow you to capture the return code on the variable rc, without interrupting your script. You could even extend this last option to capture and process the return code on the same line without risking to trigger an exit:
grep -i something file.txt || rc="$?" && echo rc="$?" > somefile.txt && command || :
The last bit ||: will guarantee that the line above always returns a return code = 0 (true).
–
–
–
–
A form without variable name repetition -- rc=$(<command> && echo $? || echo $?) -- has an expression rvalue but would also capture the stdout of <command>1. So, it's only safe if you "know" that <command> has no normal output.
Using the a && b || c construct is safe here because rc=$? and $(echo $?) can never fail.
1Sure, you can work around this by fiddling with file descriptors, but that'd make the construct long-winded and inconvenient as a standard
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.