Functions in Bash

Functions are modular building blocks for creating powerful and modular scripts, using function makes it easy to isolate a code since it would be in a single building block, which would be isolated from the rest of the script.

To put it simply, functions are a block of code or script within a script, here are some of the uses of functions in bash

  • It can help make your script more readable and avoid writing the same code multiple times, this is call re-usability, once a function is coded, it can be applied multiple times in the script. You can also port it to another script.
  • Instead of sifting through long spaghettis of code, functions make it easier to figure out what a particular part of code is supposed to do.
  • Instead of debugging the whole code in a script, you can debug functions by enclosing into set -x and set +x to nitpick that specific function that you feel is problematic, cool right!

That said, let’s go over how to use a function in bash…

Functions exist in memory as named elements, you can either create it within your shell environment or in a script. To display the functions residing in your shell environment, you can use the run the following code:

This command would return all the inbuilt functions as well as the ones you’ve created. To see what codes a certain function has, you can use the type command, e.g:

					

user@server:~$ type _known_hosts
_known_hosts is a function
_known_hosts ()
{
    local cur prev words cword;
    _init_completion -n : || return;
    local options;
    [[ "$1" == -a || "$2" == -a ]] && options=-a;
    [[ "$1" == -c || "$2" == -c ]] && options+=" -c";
    _known_hosts_real $options -- "$cur"
}

As you can see, it indicated that the _known_hosts is a function, and it also output the code of the _known_hosts function. Now unto creating a function…

The syntax for creating a function is as follows:

function <function-name> {
<code to execute>
}

Let’s create a quick function that resides in our shell environment, we would create one in a script later.

Note: The function you create at the user prompt will be lost when the shell is closed or the function is unset. To allow the function to persist, we need to add this to the login script of our user account. 

					

function user_details {
echo
echo "User list"
who
echo
echo "User Last login"
lastlog
echo
echo "Current User"
whoami
}

The above function is a simple function that shows aggregate user details. To print the detail of the function, use the type command, e.g:

					

user@server:~$ type user_details
user_details is a function
user_details ()
{
    echo;
    echo "User list";
    who;
    echo;
    echo "User Last login";
    lastlog;
    echo;
    echo "Current User";
    whoami
}

To execute the function, you simple enter user_details, and we will see the output of the commands: who, lastlog, and whoami. This is a pretty basic function, we would expand on this later.

In getting started with the bash guide, we covered customizing script with an argument, where we pass an argument to the script, we can also do the same to function that also accepts parameters that can make our code more dynamic.

Consider the following example:

rename 's/Old/New/' *.txt

rename is a GNU rename utility that is used to change a file name, the above code would rename all the “Old” string in the file name with “New” in all jpg files.

If you are wondering what the ‘s’ those, it means to substitute. The rename utility would search for the first term “Old”, and the second term “New” is what it will be substituted with.

To move this into a function, we need to think of a great and readable name. I’ll go with rename_filename, we create it as follows:

					

function rename_filename {
rename 's/old/new/' *"$1"
}

We use positional parameters to accept command-line arguments, what I am doing is replacing the hardcoded file extension (.txt) we used previously with $1 within the function. I quoted the variable to protect against spaces within the file extension.

Let me show you an example of how to use this:

  1. Create a temporary directory e.g mkdir temp
  2. cd into the temp directory: cd temp
  3. create multiple txt files using brace extension for illustration purposes: touch old{01..100}.txt
  4. If you list the content of the directory, you’ll see you have 100 dummy files created
  5. Now copy and paste the function we just created in your shell
  6. To make use of the function simply type rename_filename .txt
  7. Now, if you list the content of the temp directory, you’ll see the “old” string has been replaced with “new”

Output:

					

user@server:~/temp$ rename_filename .txt
user@server:~/temp$ ls
new001.txt  new010.txt  new019.txt  new028.txt  new037.txt  new046.txt  new055.txt  new064.txt  new073.txt  new082.txt  new091.txt  new100.txt
new002.txt  new011.txt  new020.txt  new029.txt  new038.txt  new047.txt  new056.txt  new065.txt  new074.txt  new083.txt  new092.txt
new003.txt  new012.txt  new021.txt  new030.txt  new039.txt  new048.txt  new057.txt  new066.txt  new075.txt  new084.txt  new093.txt
new004.txt  new013.txt  new022.txt  new031.txt  new040.txt  new049.txt  new058.txt  new067.txt  new076.txt  new085.txt  new094.txt
new005.txt  new014.txt  new023.txt  new032.txt  new041.txt  new050.txt  new059.txt  new068.txt  new077.txt  new086.txt  new095.txt
new006.txt  new015.txt  new024.txt  new033.txt  new042.txt  new051.txt  new060.txt  new069.txt  new078.txt  new087.txt  new096.txt
new007.txt  new016.txt  new025.txt  new034.txt  new043.txt  new052.txt  new061.txt  new070.txt  new079.txt  new088.txt  new097.txt
new008.txt  new017.txt  new026.txt  new035.txt  new044.txt  new053.txt  new062.txt  new071.txt  new080.txt  new089.txt  new098.txt
new009.txt  new018.txt  new027.txt  new036.txt  new045.txt  new054.txt  new063.txt  new072.txt  new081.txt  new090.txt  new099.txt

This function is still in memory, and as soon as you logout it won’t persist, however, we can add it to a login script or even a shell script.

Keep note that if you adding a function in a shell script, the functions should always be created at the start of the script as they need to be stored in memory by the time they are called.

Think of it as a portion of prepared food, your food needs to be prepared before you serve it.

Let’s create a script:

					

#!/bin/bash
# Author: The_Devsrealm_Guy
# Website: https://devsrealm.com
# Script to Rename Multiple File Names
# Last Edited: September 2020

function is_string {
if [[ -z "$1" ]] ; then
echo "You should enter the file extension you want to exectute the operation on"
exit 2
fi
}

function rename_filename {
is_string "$1"
echo "File Successfully Renamed"
rename 's/old/new/' *"$1"
}

read -p "Enter the extension you want to perform the rename operation on :" 
rename_filename "$REPLY"
exit 1

We provided two functions withing the script. The first one, is_string checks if user supplied a string, if no, it output “You should enter the file extension…”

Then we declare the rename_filename function that simply renames the file names on the extension that the user-supplied. You can see I called the is_string function within the rename_filename function.

At the bottom of the script, we have a prompt for the extension, and we then run the rename_filename function, which in turn calls the is_string function. The thing is, the function has to be created at the state of the script so they can be stored in memory before called. Remember, you need to prepare a portion of food, before serving 😉

Comment policy: Respectful and beneficial comments are welcome with full open hands. However, all comments are manually moderated and those that doesn't relate with what the passage is saying or offensive comments would be deleted. Thanks for understanding!

Leave a Reply

Your email address will not be published. Required fields are marked *