Skip to main content

Passing input to a Bash function via arguments or stdin

Published: 2019-06-29 | Lastmod: 2019-07-05

I have a collection of Bash functions that I often use. For some of them, I needed to ability to read input from all of the following:

  • positional arguments
  • stdin
  • here-strings

This was not as straight-forward as I would have hoped. After much trial and error, though, here’s what I came to. We’ll use the length function as an example:

length() {
  local input="$([[ -p /dev/stdin ]] && cat - || echo "$@")"
  [[ -z "$input" ]] && return 1 
  echo "${#input}"
}

It can be used in the following ways:

$ length hey
3
$ echo hey | length
3
$ length <<< echo hey
3

Here’s how it works: First, check if stdin was given:

[[ -p /dev/stdin ]]

If it was, then read from it:

cat -

If not, then read in all positional arguments:

echo "$@"

All of this is assigned to the local variable input. Next, check if input is empty:

[[ -z "$input" ]]

If it is, then return a non-zero exit code:

return 1 

Finally, if input has a value, then get its length:

echo "${#input}"