Josja
Josja

Reputation: 141

Generate other exit behavior if output from pipeline is empty

I have a bash shell script doing sth like

#!/bin/bash
# construct regex from input
# set FILE according to input file
egrep "${regex}" "${FILE}" | doing stuff | sort

I want this script to write the output (a list of new line separated matches) of the command to stdout if matches are found (which it is doing). If no matches are found it needs to write out an error message to stderr and exit with exit status 3.

I tried this

#!/bin/bash
# construct regex from input
# set FILE according to input file
function check () {
  if ! read > /dev/null
    then
      echo "error message" 1>&2
      exit 3
  fi
}
egrep "${regex}" "${FILE}" | doing stuff |
sort | tee >(check)

Now the correct error message is written out but the exit status "cannot escape the subshell"; the outer script is still exiting with exit status 0.

I also tried sth like

#!/bin/bash
# construct regex from input
# set FILE according to input file
if ! egrep "${regex}" "${FILE}" | doing stuff | sort
then
  echo "error message" 1>&2
  exit 3
fi

But here I have the problem that one of the commands in the pipe (especially sort) exits with an exit status 0

How can I get my desired exit status 3 and error message while keeping the output for normal execution and without doing all the stuff twice?

EDIT: I can solve the problem by using

#!/bin/bash
# construct regex from input
# set FILE according to input file
if ! egrep "${regex}" "${FILE}" | doing stuff | sort | grep . 
then
  echo "error message" 1>&2
  exit 3
fi

However I am not sure this is the best way since pipes are working in parallel...

Upvotes: 2

Views: 225

Answers (1)

shawn-ogg
shawn-ogg

Reputation: 26

I would use the PIPESTATUS to check the exit code of egrep:

#!/bin/bash
# construct regex from input
# set FILE according to input file
egrep "${regex}" "${FILE}" | doing stuff | sort
if [[ ${PIPESTATUS[0] != 0 ]]; then
  echo "error message" 1>&2
  exit 3
fi

Some context:

${PIPESTATUS[@]} is just an array wich contains the exit code of every program you chained up. $? will just give you the exit code of the last command in the pipe.

Upvotes: 1

Related Questions