Topic 11
5/14/2021
1
Topic 11
FUNCTIONS
Your first shell function
You can create a function within the shell as well as within a bash script
$ hello() { echo ‘Hello world!’; }
$ hello
Output:
Hello World
Note: You need the semi-colon when defining command line functions.
5/14/2021
2
Passing arguments to a function
We can pass in arguments to function just like we pass arguments to a script
$ hello() { “Hello $1, welcome to CS18!.”;}
$ hello Juan
Sample output:
Hello Juan, welcome to CS18!
Displaying functions
To display defined functions use the declare command.
$ declare –F
Sample output:
declare -f command_not_found_handle
declare -f dequote
declare -f hello
declare -f quote
declare -f quote_readline
5/14/2021
3
Display function source code
To view the function names and the source code use the –f option
To view all of the functions:
$ declare –f
Or
$ declare –f | less
To specify a specific function:
$ declare –f hello
For more info: $ help declare
Removing shell functions
You can remove shell functions by using the unset command
$ unset –f hello
$ hello
Output:
Command ‘hello’ not found, but can be installed
5/14/2021
4
Defining Functions
To define a function we use the following syntax:
name() compound_command
OR
function name { #more common in ksh shell but works in bash too
command1
command2
}
OR
function name() { ## bash-only hybrid
command1
command2
}
Defining Functions – one line syntax
One line functions inside{ …} must end with a semicolon:
function name { command1; command2; command;}
OR
name() { command1; command2; command;}
5/14/2021
5
Writing functions
Functions definitions should appear at the beginning of the script.
You can create a functions file to store functions that you regularly use.
◦ /etc/init.d/functions is the default functions file which contains functions to be used by most or all shell
scripts in the /etc/init.d directory. This file can be loaded as needed.
All shell functions are treated as a command.
You must load a function file at the start of a script using source or (.) command:
. /path/to/functions.sh
OR
source /path/to/functions.sh
You can call a function like a normal command.
Passing arguments into a function
Just like bash scripts, shell functions have their own command line arguments.
We can use $1, $2, … $n to access the arguments passed into the function.
$0 points to the shell script name, not the function name
$* or $@ holds all parameters or arguments passed to the function
$# holds the number of positional parameters passed to the function
To display the function name, use the array variable FUNCNAME, which contains the names of
all shell functions currently in the execution stack. Variable exists only when a shell function is
running.
5/14/2021
6
#!/bin/bash
# write a function
fresh(){
# t stores $1 argument passed to fresh()
t=$1
echo “fresh(): \$0 is $0”
echo “fresh(): \$1 is $1”
echo “fresh(): \$t is $t”
echo “fresh(): total args passed to me $#”
echo “fresh(): all args (\$@) passed to me -\”$@\””
echo “fresh(): all args (\$*) passed to me -\”$*\””
}
# invoke the function with “Tomato” argument
echo “**** calling fresh() 1st time ****”
fresh Tomato
# invoke the function with total 3 arguments
echo “**** calling fresh() 2nd time ****”
fresh Tomato Onion Paneer
#!/bin/bash
# funcback.sh : Use $FUNCNAME
backup(){
local d=”$1″
[[ -z $d ]] && { echo “${FUNCNAME}(): directory name not
specified”; exit 1; }
echo “Starting backup…”
}
backup $1
5/14/2021
7
#!/bin/bash
file=”$1″
# User-defined function
is_file_dir(){
# $f is local variable
local f=”$1″
# file attributes comparisons using test i.e. [ … ]
[ -f “$f” ] && { echo “$f is a regular file.”; exit 0; }
[ -d “$f” ] && { echo “$f is a directory.”; exit 0; }
[ -L “$f” ] && { echo “$f is a symbolic link.”; exit 0; }
[ -x “$f” ] && { echo “$f is an executeble file.”; exit 0; }
}
# make sure filename supplied as command line arg else die
[ $# -eq 0 ] && { echo “Usage: $0 filename”; exit 1; }
# invoke the is_file_dir and pass $file as arg
is_file_dir “$file”
Run as follows:
./cmdargs.sh /etc/resolv.conf
./cmdargs.sh /bin/date
./cmdargs.sh $HOME
./cmdargs.sh /sbin
Sample outputs:
/etc/resolv.conf is a regular file.
/bin/date is a regular file.
/home/vivek is a directory.
/sbin is a directory.
5/14/2021
8
Local variables
By default all variables are global.
Modifying a variable in a function changes it in the whole script.
Returning from a function
Bash functions, unlike functions in most programming languages do not allow you to return a
value to the caller.
When a function ends its return value is its status: zero for success, non-zero for failure
Bash has a return statement, but we can only specify the function’s status, which is a numeric
value like specified with return statements.
◦ Status value stored in $?
◦ If function does not return a value, its status is set based on the status of the last statement executed in
the function.
A few options for returning values
◦ Set a global variable with the result
◦ Use command substitution
◦ Pass in the name of a variable to use as the result variable
5/14/2021
9
Returning from a function – global
variable
Simplest way to return a value from a function is to just set a global variable to the result. Recall
that in bash variables are global by default.
function myfunc()
{
myresult=‘some value’
}
myfunc
echo $myresult
Returning from a function – local
variables
Global variables in large programs will lead to difficult to find bugs.
Better approach is to use local variables, but then how do you get the result to the caller. You
can use command substitution
function myfunc()
{
local myresult=‘some value’
echo “$myresult”
}
result=$(myfunc) #or result=`myfunc`
echo $myresult
5/14/2021
10
Returning from a function – passing in a
variable
The other way is to write your function so that it accepts a variable name as part of its command line
and then set that variable to the result of the function.
function myfunc()
{
local _resultvar=$1
local myresult=‘some value’
eval $__resultvar=“’$myresult’”
}
myfunc result
echo $result