Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is grep "-c" with 0 count exits program with status code -1

Tags:

grep

bash

count

why is that when grep -c returns 0, script fails with '-1' exit code. This happens only when set -o errexit is set.

Copy/Paste on a bash shell

cat <<'EOT' > /tmp/foo.sh
#!/usr/bin/env bash

function bash_traceback() {
  local lasterr="$?"
  set +o xtrace
  local code="-1"
  local bash_command=${BASH_COMMAND}
  echo "Error in ${BASH_SOURCE[1]}:${BASH_LINENO[0]} ('$bash_command' exited with status $lasterr)"
  if [ ${#FUNCNAME[@]} -gt 2 ]; then
    # Print out the stack trace described by $function_stack
    echo "Traceback of ${BASH_SOURCE[1]} (most recent call last):"
    for ((i=0; i < ${#FUNCNAME[@]} - 1; i++)); do
    local funcname="${FUNCNAME[$i]}"
    [ "$i" -eq "0" ] && funcname=$bash_command
    echo -e "  $i: ${BASH_SOURCE[$i+1]}:${BASH_LINENO[$i]}\t$funcname"
    done
  fi
  echo "Exiting with status ${code}"
  exit "${code}"
}

test_redirecting_of_stdout_stderr() {

    # Exit program when error found
    set -o errexit

    # Exit program when undefined variable is being used
    set -o nounset

    local up_count
    up_count=$(ls | grep -c NOTHING_MATCHED)
    echo "up_count: $up_count"
}

# provide an error handler whenever a command exits nonzero
trap 'bash_traceback' ERR

set -o errtrace

test_redirecting_of_stdout_stderr

EOT

bash /tmp/foo.sh

Output

debian:~/my-mediawiki-docker$ bash /tmp/foo.sh
Error in /tmp/foo.sh:31 ('up_count=$(ls | grep -c NOTHING_MATCHED)' exited with status 255)
Traceback of /tmp/foo.sh (most recent call last):
  0: /tmp/foo.sh:31     up_count=$(ls | grep -c NOTHING_MATCHED)
  1: /tmp/foo.sh:40     test_redirecting_of_stdout_stderr
Exiting with status -1
debian:~/my-mediawiki-docker$
like image 759
amulllb Avatar asked Dec 10 '16 18:12

amulllb


1 Answers

grep reports "failure" if it fails to find any matching lines. Here's man grep:

EXIT STATUS
       The exit status is 0 if selected lines are found, and 1 if not found. 

If you want to allow a command to exit with non-zero without terminating the script during errexit, use || true:

up_count=$(ls | grep -c NOTHING_MATCHED) || true
like image 109
that other guy Avatar answered Sep 20 '22 01:09

that other guy