bash has functions, but they don’t behave like functions in other programming languages. instead they behave like regular shell commands.

How do regular shell commands behave? They take in arguments separated by space, they have exit status number, they can write to stdout and stderr, they can read from stdin.. and finally they can be piped to other shell commands.

Functions can do all that.

Defining parameters and passing arguments

u can’t define parameter signature in a bash function. but the passed in arguments are accessed inside the function with positional arg vars like $1, $2 etc.

And with "$@", u can iterate over the passed in args in a loop.
And with $*, all the passed in args will be slurped up into a single string. (So be careful.)

log() {
  timestamp=$(date -Iseconds)
  for arg in "$@"; do
    echo "[$timestamp]:$arg"
  done
}

calling it like log "blah" "blue" "blay foo" will output:

[2026-07-05T17:24:34+05:30]:blah
[2026-07-05T17:24:34+05:30]:blue
[2026-07-05T17:24:34+05:30]:blay foo

Returning something from a function

If u want the function to return a value, use echo or printf (better) to write to stdout. Do this as the last part of the function body. And then at the caller side, u can assign it to a variable using var=$(fncall).

answer() {
  printf "it is %d\n" "42"
}

answer # this is a function call
b=$(answer) # this too is a function call, captured in a var
echo $b

A function call’s exit status - an int between 0 to 255 - is the exit status of the last command/expression that ran in that function.

But you can return a specific code preemptively with the return keyword. (But this isn’t commonly used, and is confusing.)

answer() {
  echo "aa"
  return 254
  echo "bb" # doesn't get executed
}

answer # aa
echo $? # 254

Within a function, always declare local variables so as not to pollute the global vars defined elsewhere in the script. Do it with local keyword:

  • declare ints with local -i count=1
  • arrays with local -a arr=(item1 item2 item3)
  • hashes with local -A hash=([k1]=v1 [k2]=v2 [k3]=v3)
  • readonly var with local -r pi="3.14"