New to bash or shell scripting? Let's start learning. Bash scripting can be considered the first step to learn programming languages. You may be in any IT stream but there will come a point in your career where you will end up writing your first shell script. So let us start learning about, how we can define bash function?
I have written this tutorial considering absolute beginners who have just started with shell scripting. For experience users, you may skip the lecture.
What is a function in bash?
- The definition of
functionwill not change only for bash and will remain same across all programming languages - Although there may be few functional changes so we will only talk about shell function
- A
functioncan be considered as command which internally is a combination of multiple commands, values, positional parameters etc - So we club all these values, commands together into a single
functionso it becomes easier for us to use the same set of commands together
Confused? Why do I need to use function?
Let us take a simple example. We have to perform below set of tasks
1. Create 100 Users
2. Assign different password to individual users
3. Make sure the user changes password on it's first login
4. Assign separate home directory for the user
- We have a bunch of tasks to be done
- We can go ahead and write individual commands for each tasks, OR
- We define a function and put all the commands, variables into this one single function (or you may create more than one function)
- Using this single function we would be able to perform all the tasks
- Still wondering why we need a function for this, why not just call it in plain script?
- Yes TRUE, we can call these commands in plain script but imagine you have 10000+ lines of code, wouldn't it be easier if we had it arranged in separate function where each function does it's own job
For example:
1. One function to create users and assign passwords
2. Another one to handle it's home directories
3. Last one to make sure user changes it's password after first login
This is all very theoretical, I will show you some real time practical examples to help you understand better.
How do we define bash function?
The basic syntax to define a function in shell script would be
<function_name> [()] {
compound-command
}
OR you can also use
function <function_name> [()] {
compound-command
}
What is the difference between these function syntax?
You must be wondering which of these syntax should I choose to write my first function?
The one liner answer is that "you can use any of the above syntax" but I would recommend to also read below:
The detailed answer is:
functionkeyword is originally used with KSH shell- Later bash shell also introduced support for
functionkeyword - There is no reason to use
parenthesiswhile defining a function, although bash man page does mentions about usingparenthesiswithfunction - But we never know as the support for
()may be removed in future bash version - So the recommended syntax for shell script with global support would be
function <function_name> {
compound-command
[redirection]
}
To learn more about the different syntax and their behaviour you can read more at Unix Stack Exchange
Understanding the function syntax
- You define your bash
functionname by replacingfunction_namein the syntax - There is no such restriction while choosing for
functionname. It can contain solely letters, numbers, and underscores, and beginning with a letter or underscore. - The block between curly braces
{}is the main function block where you will place your commands - Unlike some of the programming language, there is no such restriction to put semi-colon "
;" after every command - But if you plan to write two different command in same line then you must use semi-colon "
;", for example,command 1; command 2
# cat /tmp/shell_script.sh 1 #!/bin/bash 2 3 function print_name { 4 echo "My name is Deepak" 5 } 6 7 # Call your function 8 print_name
- In
Line 3we have defined ourfunctionprint_nameand starting of our function block withOPENcurly brace{ Line 4contains the command to be executed inside thefunctionbodyLine 5contains theCLOSEcurly braces}- On
Line 8we will call our function by just writing thefunctionname. No special handling needed
This function will only execute echo "My name is Deepak" on the terminal screen, the output from this script:
# /tmp/shell_script.sh My name is Deepak
You must provide executable permission to this script chmod u+x /tmp/shell_script.sh
Local and Global variables
Now since you know about bash function, you should be really careful the way you would define your VARIABLES
Why do I need VARIABLES in script?
- It is strongly recommended to use VARIABLES as much as possible while writing any script
- As it avoids writing hard code and repetitive values
- Let's assume you have to use a file from
/tmp/dir1/file at different location in your script which you define manually without using variables - Now few days later you realise that the path needs to be changed to
/tmp/dir2/file, now imagine doing this task at all the places within the script and if you miss to update even at one place then the script would fail - So we create one variable with name name such as
FILE_PATH=/tmp/dir1/fileand I will use this variable$FILE_PATHacross the script. Now even if you have to change the path you just update this one variable and you are good to do go..
It is important you understand the difference between Local and Global Variable. Let us look at this sample script:
1 #!/bin/bash 2 3 SOME_VAR="GLOBAL" 4 5 function print_name { 6 SOME_VAR="LOCAL" 7 echo "My name is Deepak" 8 } 9 10 # Check the value of VARIABLE before we call the function 11 echo "Before calling function, SOME_VAR: $SOME_VAR" 12 13 # Call your function 14 print_name 15 16 # Check the value of VARIABLE after we call the function 17 echo "After calling function, SOME_VAR: $SOME_VAR"
The output from this script:
Before calling function, SOME_VAR: GLOBAL My name is Deepak After calling function, SOME_VAR: LOCAL
What do we understand?
Line 3we have definedSOME_VARwhich will be our global variableLine 6we have re-definedSOME_VARinside the function print_name block, since this is limited to thefunctionblock, it will be considered as local variableLine 11we check the value ofSOME_VAR. At this stage since the function print_name is not executed yet, so the content ofSOME_VARwould be "GLOBAL"Line 14we execute the function which would also execute theSOME_VARvariable within the function block- In
Line 17we re-check the content ofSOME_VARand now it will be changed toLOCALbecause the functionprint_namehas now made this as global variable - So after
Line 14, any command or function if tries to useSOME_VARthen the value of this variable would beLOCAL
Call bash function with arguments
- We also have an option to pass input arguments to the bash
function. - Why would you need that you ask?
- Imagine you are trying to write a
functionto compare two integers but these integers will be provided by end user as command line argument - So how will function access these integer values for comparison?
- We can pass them as an input to the script which will further be passed to the function
- To pass values within the script you should pass the values just next to the
functionseparated by single white space character
The syntax to for this would be:
function_name "[arg1]" "[arg2]" "[arg3]" ..
To store this you should also collect these input values within your function. You can use any variable name, I have used ARG1, ARG2, ARG3 here..
function function_name {
ARG1="$1"
ARG2="$2"
ARG3="$3"
COMMANDS
}
Or you can pass all the input values into single array/variable
function_name string1 string2 string3
To store this you should also collect these input values within your function into a single array/variable
function function_name {
ARG="$@"
COMMANDS
}
Pass and store input arguments into different Variables
In this sample shell script, I have passed three input strings to my bash function pass_arg
And I am storing these three strings into three different variables and then printing the content of this variable. It is recommended to put all the input values into inverted commas " " assuming anyone of these input values contains white space.
#!/bin/bash
function pass_arg {
# Collect Input Values
ARG1="$1"
ARG2="$2"
ARG3="$3"
# Print the variable content
echo "First: $ARG1"
echo "Second: $ARG2"
echo "Third: $ARG3"
}
# Executing the function
pass_arg "argument1" "argument2" "argument3"
From the output from this script we see the script was successfully able to store all the three input values into three different variables:
First: argument1 Second: argument2 Third: argument3
Pass and store input arguments into single Variable
In the next sample shell script, I will store all the input values into single VARIABLE. In this case you should not use inverted commas " " for individual strings or else only the first value "string1" would be considered by the bash function. Either you put the entire list of strings under inverted commas like "string1 string2 string3" or you can just pass the entire list without inverted commas to your function as I have done in this script.
function pass_arg {
# Collect Input Values
ARG="$@"
# Print the variable content
echo "Input argument list: $ARG"
echo "Variable Length: ${#ARG[@]}"
}
# Call your function
pass_arg string1 string2 string3
From the output from this scrip we see the function has successfully parsed the input list of values and stored into single variable. I have also printed the variable length so that we know the script has not considered it as an array.
Input argument list: string1 string2 string3
Variable Length: 1
Even though there are 3 strings each separated by white space, bash considers it as a VARIABLE
Pass and store input arguments into Array
To store the input values as ARRAY you must make sure of two things
1. Do not pass input values under semi colon
2. Store the input values within bash function inside parenthesis
I would recommend to also read How to split string into array using 4 simple methods in bash
#!/bin/bash
function pass_arg {
# Collect Input Argument and convert the VAR to ARRAY using parenthesis
ARG=("$@")
# Print the array content
echo "Input argument list: $ARG"
echo "Variable Length: ${#ARG[@]}"
}
# Call your function
pass_arg string1 string2 string3
The output from this script:
Input argument list: string1 string2 string3 Variable Length: 3
Now bash considers ARG as ARRAY as it could identify three different strings from ARG from the length syntax.
Let me also give you one practical example on this:
In shell scripts we normally have a lot of echo statement and most of the time we have to also store these echo statements to some log files
So we create a function which will echo statement to the screen and also send the same message to a log file so that we don't have to repeat the same command twice:
#!/bin/bash # Define Log file variable LOGFILE=/var/log/myapp.log function log_content { # print on output echo "$*" # store the logs echo "$*" >> $LOFILE } # Execute the function log_content "Starting the process"
We can also enhance the function to print date and time along with hostname while storing the logs in the log file just like the format as we have messages in /var/log/messages
#!/bin/bash
# Define Log file variable
LOGFILE=/var/log/myapp.log
function log_content {
# print on output
echo "$*"
# store the logs with timestamp
echo "`date +"%b %e %T"` `hostname` "$*" >> LOGFILE
}
# Execute the function
log_content "Starting the process"
So now we have a function which taken input values and then use it to print the info on screen and also store it in log file.
Collect command line arguments from end user and pass it to function
- You can also collect input from end user as command line argument and then pass it as an input to the function
- We are storing the input values into single variable i.e.
ARG - Then we are passing this variable to the
function - Next inside the function we need to again collect and store it in a different variable
INPUT_ARGfor further processing - Now you can use
INPUT_ARGwithin yourfunction
#!/bin/bash ARG="$*" function pass_arg { INPUT_ARG="$1" echo "Input Argument: $INPUT_ARG" } # Call your function pass_arg "$ARG"
Then we execute the script with an input value as "deepak"
# /tmp/shell_script.sh deepak Input Argument: deepak
The function has collected the input value, stored it in ARG then this $ARG was passed on to the function. The function read this input and stored it in INPUT_ARG which was later used as $INPUT_ARG.
Use Return Values in Function
- When working with bash functions, you must be familiar with
returnkeyword used inside function - You cannot use
returnoutsidefunctionblock - In layman's terms,
returnis used as an alternate forexitstatement. (Although both are not same) - The advantage with
returnis that you can choose to come out of afunctionwithout actually coming out of the script. - If you have already heard of
continue,breakas I explained in my earlier articles withforandwhileloop then you may get confuse withreturnas it may sound familiar continueandbreakare used to come out of the loop conditions only but the additional advantage withreturnis to pass an exit code also while coming out of the loop
Let us use this in shell script to understand the usage properly:
Line 3we have defined a function return_valueLine 5we are printing a simple statement on the screen using echoLine 6-10we are check the exit status of echo command- At
Line 7if the exit status is 0 thenreturn 0will be called - If the exit status in non-zero then at
Line 9,return 1would be called - At
Line 13we have defined another echo statement within the samefunctionblock - NOW the mistake which I have done is that I have also put an
echoafter thereturnvalue. This section will never be called, so look out for such scenarios. - Please NOTE If your loop triggers return value then the remaining part of the
functionwill not be executed Line 18we execute thefunctionand again atLine 19we check the exist status of thefunctionLine 21we print a statement with the exit code of thefunction. This exit code should match thereturncode from within thefunctionblock
1 #!/bin/bash 2 3 function return_values { 4 5 echo "We do something" 6 if [ $? == 0 ];then 7 return 0 8 else 9 return 1 10 fi 11 12 # This will not be called as the function will exit at return stage above 13 echo "Good Day" 14 15 } 16 17 # Call your function 18 return_values 19 exit_status=$? 20 21 echo "The exit status of function is: $exit_status"
Now we execute the script, the exit code of our script is same as function's return value
We do something The exit status of function is: 0
We know we did some mistakes in the above script, The proper way to write above script would be:
#!/bin/bash
function return_values {
echo "We do something"
if [ $? != 0 ];then
return 1
fi
# This will not be called as the function will exit at return stage above
echo "Good Day"
return 0
}
# Call your function
return_values
exit_status=$?
echo "The exit status of function is: $exit_status"
So now we don't exit at the first command instead we add a negative check. The bash function will exit only if the first echo statement fails or else we will get both the echo statement
The output from this script would be:
We do something
Good Day
The exit status of function is: 0
Conclusion
To define a bash function is something is very much important to streamline the script content. Without functions your code may become very messy.
Secondly you should also make an habit to put a description field above every function which explains about the function you have written. Also if the function accepts any input argument then those should be mentioned so that if any third person reads your script then he/she will understand the role of individual function
Lastly I hope the steps from the article to define function in bash on Linux and Unix was helpful. So, let me know your suggestions and feedback using the comment section.

