Home > Enterprise >  Make a bash function fail when on empty
Make a bash function fail when on empty

Time:11-22

I want to write a function that always have a non empty output or fails, but I'm missing a command that read stdin and pipe it to stdout if non-empty or fails like:

example() {
  do_something_interesting_here $1 | cat_or_fails
}

The idea is that if the command cat_or_fails is given an empty input it fails (so the function fails) or the input is output without any changes (like cat).

But I could not find any standard utility capable of that trick, or may be I'm not sure how to use those tools.

CodePudding user response:

Following the idea of @William Pursell in the comment it seems that grep can do the trick using something like:

example() {
  do_something_interesting_here $1 | grep "[[:alnum:]]"
}

As mentioned in the comments, it will consume any empty lines (or any line that don't match the regex given).

CodePudding user response:

A simple algorithm to accomplish this is trivial and obvious: Try to read one byte. If it works, write that byte back out and then run cat. If it fails, exit with a nonzero status.

Both below variants can be used in the manner described in the question (... | cat_or_fails).


A very simple implementation (that doesn't try to handle binary files) would look like:

cat_or_fails() {
  local firstbyte
  IFS= read -r -n 1 firstbyte || return
  printf '%s' "${firstbyte:-$'\n'}"
  cat
}

A slightly less simple implementation that does try to handle binary files correctly might look like:

cat_or_fails() {
  local firstbyte
  IFS= read -r -d '' -n 1 firstbyte || return
  if [[ $firstbyte ]]; then
    printf '%s' "$firstbyte"
  else
    printf '\0'
  fi
  cat
}

CodePudding user response:

My usual trick to assure that at least one line of a text file is found follows. It is all standard shell stuff... bash, ksh, zsh.

example() {
  set -o pipefail     #assure failure on do_something is not suppressed
  do_something_interesting_here $1 | 
       grep .           #assure no output returns error
}

If you need pipefail to cancel when the function returns:

example() {
 (   #isolate pipefail in subshell
  set -o pipefail     #assure failure on do_something is not suppressed
  do_something_interesting_here $1 | 
       grep .           #assure no output returns error
 )
}
  • Related