BeeOnRope
BeeOnRope

Reputation: 64895

Elegant way to capture exit code of command in a set -e script

I have a script usually running under set -e (specifically, set -euo pipefail).

One particular command, grep, I expect to sometimes return a non-zero exit code and I want to take some action depending on the specific return code rather than simply whether the command failed1.

Something like:

grep ...
if [[ $? -eq ... ]]; then
  ...
fi

This will fail under set -e if grep returns a non-zero exit code, so I'll never get to my if. I can't just run it directly in the if like if grep ...; then since I care about more than just 0 and non-zero.

I don't want to disable set -e temporarily as this is ganky and clobbers the e state in case I wasn't running under set -e in the first place.

This is what I came up with:

{ grep ...; gexit=$?; } || true
if [[ $gexit -eq ... ]]; then
...

Certainly there must be something better?


1 Specifically, grep is a bit unusual in that it returns an exit code of 0, 1 or 2 for "1+ matches", "0 matches" and "error", respectively. I'm not looking for a grep-specific answer, however.

Upvotes: 1

Views: 1310

Answers (2)

oguz ismail
oguz ismail

Reputation: 50750

Depends on how you define elegant. This is elegant to me:

if
  grep ...
  [[ $? -eq ... ]]
then
  ...

But not very useful, as the exit status of grep is immediately lost and can't be examined any further. This, on the other hand, doesn't have that problem:

if grep ...; then
  # handle zero
  ...
else
  # handle non-zero
  case $? in
  ...)
    ...
  esac
fi

Upvotes: 4

Jetchisel
Jetchisel

Reputation: 7791

This will fail under set -e if grep returns a non-zero exit code, so I'll never get to my if

Testing the grep command and it's arguments inside the if statement does not exit immediately with set -e enabled even if the exit status of grep is non-zero

#!/usr/bin/env bash

set -e

if grep -q somestring somefile; then
  echo good
else
  echo bad
fi

I've tested both with bash and dash.

Upvotes: 0

Related Questions