Bash Scripting Part6 – Create and Use Bash Functions
Before we talk about bash functions, let’s discuss this situation. When writing bash scripts, you’ll find yourself that you are using the same code in multiple places.
If you get tired of writing the same lines of code again and again in your bash script, it would be nice to write the block of code once and call it anywhere in your bash script.
The bash shell allows you to do just that with Functions.
Bash functions are blocks of code that you can reuse them anywhere in your code. Anytime you want to use this block of code in your script, you simply type the function name given to it.
We are going to talk about how to create your bash functions and how to use them in shell scripts.
Creating a function
You can define a function like this:
functionName() { }
The brackets () are required to define the function.
Also, you can define the function using the function keyword, but this keyword is deprecated for POSIX portability.
function functionName() { # Deprecated definition but still used and working }
In the second definition, the brackets are not required.
Using functions
#!/bin/bash myfunc() { echo "Using functions" } total=1 while [ $total -le 3 ]; do myfunc total=$(($total + 1)) done echo "Loop finished" myfunc echo "End of the script"
Here we’ve created a function called myfunc, and to call it, we just typed its name.
You can call the function many times as you want.
Notice: If you try to use a function which is not defined, what will happen?
#!/bin/bash total=1 while [ $total -le 3 ]; do myfunc total=$(($total + 1)) done echo "Loop End" myfunc() { echo "Using function ..." } echo "End of the script"
Oh, it’s an error because there no such function.
Another notice: bash function name must be unique. Otherwise, the new function will cancel the old function without any errors.
#!/bin/bash myfunc() { echo "The first function definition" } myfunc function myfunc() { echo "The second function definition" } myfunc echo "End of the script"
As you can see, the second function definition takes control from the first one without any error, so take care when defining functions.
Using the return command
The return command returns an integer from the function.
There are two ways of using the return command; the first way is like this:
#!/bin/bash myfunc() { read -p "Enter a value: " value echo "adding value" return $(($value + 10)) } myfunc echo "The new value is $?"
The myfunc function adds 10 to the $value variable then shows the sum using the $? Variable.
Don’t execute any commands before getting the value of the function, because the variable $? returns the status of the last line.
This return method returns integers. What about returning strings?
Using function output
The second way of returning a value from a Bash function is command substitution. This way, you can return anything from the function.
#!/bin/bash myfunc() { read -p "Enter a value: " value echo $(($value + 10)) } result=$(myfunc) echo "The value is $result"
Passing parameters
We can deal with bash functions like small snippets that we can reuse, and that’s OK, but we need to make the function like an engine, we give it something, and it returns a result based on what we provide.
You can use the environment variables to process the passed parameters to the function. The function name is declared as $0 variable, and the passed parameters are $1, $2, $3, etc.
You can get the number of passed parameters to the function using the ($#) variable.
We pass parameters like this:
myfunc $val1 10 20
The following example shows how to use the ($#) variable:
#!/bin/bash addnum() { if [ $# -gt 2 ]; then echo "Incorrect parameters passed" # If parameters no equal 2 else echo $(($1 + $2)) # Otherwise add them fi } echo -n "Adding 10 and 15: " value=$(addnum 10 15) echo $value echo -n "Adding three numbers: " value=$(addnum 10 15 20) echo $value
The addnum function gets the count of the passed parameters. If greater than 2 passed, it returns -1.
If there’s one parameter, the addnum function adds this parameter twice. If two parameters passed, the addnum function adds them together, and if you try to add three parameters, it will return -1.
If you try to use the passed parameters inside the function, it fails:
#!/bin/bash myfunc() { echo $(($1 + $2 + $3 + $4)) } if [ $# -eq 4 ]; then value=$(myfunc) echo "Total= $value" else echo "Passed parameters like this: myfunc a b c d" fi
Instead, you have to send them to the function like this:
#!/bin/bash myfunc() { echo $(($1 + $2 + $3 + $4)) } if [ $# -eq 4 ]; then value=$(myfunc $1 $2 $3 $4) echo "Total= $value" else echo "Passed parameters like this: myfunc a b c d" fi
Now it works!!
Processing variables in Bash functions
Every variable we use has a scope; the scope is variable visibility to your script.
You can define two types of variables:
- Global
- Local
Global variables
They are visible and valid anywhere in the bash script. You can even get its value from inside the function.
If you declare a global variable within a function, you can get its value from outside the function.
Any variable you declare is a global variable by default. If you define a variable outside the function, you call it inside the function without problems:
#!/bin/bash myfunc() { input=$(($input + 10)) } read -p "Enter a number: " input myfunc echo "The new value is: $input"
If you change the variable value inside the function, the value will be changed outside of the function.
So how to overcome something like this? Use local variables.
Local variables
If you use the variable inside the function only, you can declare it as a local variable using the local keyword like this:
local tmp=$(( $val + 10 ))
So if you have two variables, one inside the function and the other is outside the function, and they have an identical name, they won’t affect each other.
#!/bin/bash myfunc() { local tmp=$(($val + 10)) echo "The Temp from inside function is $tmp" } tmp=4 myfunc echo "The temp from outside is $tmp"
When you use the $tmp variable inside the myfunc function, it doesn’t change the value of the $tmp, which is outside the function.
Passing arrays as parameters
What will happen if you pass an array as a parameter to a function:
#!/bin/bash myfunc() { echo "The parameters are: $@" arr=$1 echo "The received array is ${arr[*]}" } my_arr=(5 10 15) echo "The old array is: ${my_arr[*]}" myfunc ${my_arr[*]}
The function only takes the first value of the array variable.
You should disassemble the array into its single values, then use these values as function parameters. Finally, pack them into an array in the function like this:
#!/bin/bash myfunc() { local new_arr new_arr=("$@") echo "Updated value is: ${new_arr[*]}" } my_arr=(4 5 6) echo "Old array is ${my_arr[*]}" myfunc ${my_arr[*]}
The array variable was rebuilt thanks to the function.
Recursive function
This feature enables the function to call itself from within the function itself.
The classic example of a recursive function is calculating factorials. To calculate the factorial of 3, use the following equation:
3! = 1 * 2 * 3
Instead, we can use the recursive function like this:
x! = x * (x-1)!
So to write the factorial function using bash scripting, it will be like this:
#!/bin/bash fac_func() { if [ $1 -eq 1 ]; then echo 1 else local tmp=$(($1 - 1)) local res=$(fac_func $tmp) echo $(($res * $1)) fi } read -p "Enter value: " val res=$(fac_func $val) echo "The factorial of $val is: $res"
Using recursive bash functions is so easy!
Creating libraries
Now we know how to write functions and how to call them, but what if you want to use these bash functions or blocks of code on different bash script files without copying and pasting it on your files.
You can create a library for your functions and point to that library from any file as you need.
By using the source command, you can embed the library file script inside your shell script.
The source command has an alias, which is the dot. To source a file in a shell script, write the following line:
. ./myscript
Let’s assume that we have a file called myfuncs that contains the following:
addnum() { echo $(($1 + $2 + $3 + $4)) }
Now, we will use it in another bash script file like this:
#!/bin/bash . ./myfuncs result=$(addnum 10 10 5 5) echo "Total = $result"
Awesome!! We’ve used the bash functions inside our bash script file; we can also use them in our shell directly.
Use Bash functions from the command line
Well, that is easy, if you read the previous post, which was about the signals and jobs, you will have an idea about how to source our functions file in the bashrc file, and hence we can use the functions directly from the bash shell. Cool
Edit the bashrc file at /home/username and add this line:
. /home/likegeeks/Desktop/myfuncs
Make sure you type the correct path.
Now the function is available for us to use in the command line directly:
$ addnum 10 20
Note: you may need to log out and log in to use the bash functions from the shell.
Another note: if you make your function name like any of the built-in commands, you will overwrite the default command so you should take care of that.
Mokhtar is the founder of LikeGeeks.com. He is a seasoned technologist and accomplished author, with expertise in Linux system administration and Python development. Since 2010, Mokhtar has built an impressive career, transitioning from system administration to Python development in 2015. His work spans large corporations to freelance clients around the globe. Alongside his technical work, Mokhtar has authored some insightful books in his field. Known for his innovative solutions, meticulous attention to detail, and high-quality work, Mokhtar continually seeks new challenges within the dynamic field of technology.
Loving your site and the tutorials, Doing a great job, please keep up the good work !
Thanks for the great comment.
I’ll do my best
How to do floating point division in bash script and also how to use trigonometric function like sin and cos .
I was planning to make more posts about Bash scripting but anyway,
you can use double quotes with bc command for floating points like this
#!/bin/bash
a=50
b=3
echo "$a / $b" | bc -l
The result should be something like that 16.66666666666666666666
Regarding trigonometric functions, I use something like awk
$ awk 'BEGIN{print sin(90)}'
Hope you find what you need.
Thank you
i liked your scripts…
Thanks!