I have to write a function in bash. The function will take about 7 arguments. I know that I can call a function like this:
To call a function with parameters:
function_name $arg1 $arg2
And I can refer my parameters like this inside the function:
function_name () { echo "Parameter #1 is $1" }
My question is, is there a better way refer to the parameters inside the function? Can I avoid the $1, $2, $3, .... thing and simply use the $arg1, $arg2, ...?
Is there a proper method for this or do I need to re-assign these parameters to some other variables inside the function? E.g.:
function_name () { $ARG1=$1 echo "Parameter #1 is $ARG1" }
Any example would be much appreciated.
A positional parameter is a parameter denoted by one or more digits, other than the single digit 0 . Positional parameters are assigned from the shell's arguments when it is invoked, and may be reassigned using the set builtin command.
In many cases, bash scripts require argument values to provide input options to the script. You can handle command-line arguments in a bash script in two ways. One is by using argument variables, and another is by using the getopts function.
Bash uses whitespace to determine where words begin and end. The first word is the command name and additional words become arguments to that command.
There are no Booleans in Bash. However, we can define the shell variable having value as 0 (“ False “) or 1 (“ True “) as per our needs. However, Bash also supports Boolean expression conditions.
The common way of doing that is assigning the arguments to local variables in the function, i.e.:
copy() { local from=${1} local to=${2} # ... }
Another solution may be getopt-style option parsing.
copy() { local arg from to while getopts 'f:t:' arg do case ${arg} in f) from=${OPTARG};; t) to=${OPTARG};; *) return 1 # illegal option esac done } copy -f /tmp/a -t /tmp/b
Sadly, bash can't handle long options which would be more readable, i.e.:
copy --from /tmp/a --to /tmp/b
For that, you either need to use the external getopt
program (which I think has long option support only on GNU systems) or implement the long option parser by hand, i.e.:
copy() { local from to while [[ ${1} ]]; do case "${1}" in --from) from=${2} shift ;; --to) to=${2} shift ;; *) echo "Unknown parameter: ${1}" >&2 return 1 esac if ! shift; then echo 'Missing parameter argument.' >&2 return 1 fi done } copy --from /tmp/a --to /tmp/b
Also see: using getopts in bash shell script to get long and short command line options
You can also be lazy, and just pass the 'variables' as arguments to the function, i.e.:
copy() { local "${@}" # ... } copy from=/tmp/a to=/tmp/b
and you'll have ${from}
and ${to}
in the function as local variables.
Just note that the same issue as below applies — if a particular variable is not passed, it will be inherited from parent environment. You may want to add a 'safety line' like:
copy() { local from to # reset first local "${@}" # ... }
to ensure that ${from}
and ${to}
will be unset when not passed.
And if something very bad is of your interest, you could also assign the arguments as global variables when invoking the function, i.e.:
from=/tmp/a to=/tmp/b copy
Then you could just use ${from}
and ${to}
within the copy()
function. Just note that you should then always pass all parameters. Otherwise, a random variable may leak into the function.
from= to=/tmp/b copy # safe to=/tmp/b copy # unsafe: ${from} may be declared elsewhere
If you have bash 4.1 (I think), you can also try using associative arrays. It will allow you to pass named arguments but it will be ugly. Something like:
args=( [from]=/tmp/a [to]=/tmp/b ) copy args
And then in copy()
, you'd need to grab the array.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With