Learning never exhausts the mind
Home >  Technology > Linux > How to Create and Use Bash Scripts

Published 25th July 2016 by

Learn how to write Bash scripts on Unix/Linux, a required skill for system administration and a handy skill for the rest of us.
{{< series_header 6755>}}

All Linux systems have a shell, the basic text-based user interface. Bash is one of the most popular and it stands for Bourne-Again SHell.

A Bash script is analogous to a DOS batch file. In it's simplest form you can run multiple commands one after another in sequence. Like DOS batch files you can build some pretty complex scripts given time. For now, we will look at how to create a few simple, useful, bash scripts.

Writing a simple Bash script

Each script starts with what's called a "shebang", followed by the path to the shell that you want the script to use.

{{< highlight bash "linenos=table" >}}#!/bin/bash{{< / highlight >}}

The "#!" characters are called the shebang.

Scripts usually have comments at the top which include author information, what the script does and usage instructions. Comments start with a hash - #.

{{< highlight bash "linenos=table" >}}#!/bin/bash # This is a comment{{< / highlight >}}

Let's say we want to create a bash script to copy some PHP files from our user development directory to the webserver root. We could manually type in the command each time, or we can create a bash script and call that instead.

Create a new file using your favourite text editor (pico for me) and enter the following lines.

{{< highlight bash "linenos=table" >}}#!/bin/bash cp *.php /usr/web/public_html{{< / highlight >}}

Save the file as something meaningful, for example publish and close the editor.

We now need to make this script executable by changing the Linux permissions.

{{< highlight bash "linenos=table" >}}chmod 700 publish{{< / highlight >}}

This will let you, and only you, read, write, and execute the script.

From within the directory you created the script in, you can enter publish on the command line and it will then execute the command to copy the files to the webserver.

Using Variables in a Bash script

Variables are a key component of programming. Variables allow a programmer to store data, alter and reuse them throughout the script.

There are two types of variables - system and user. System variables are created and maintained by the system. They are designated with CAPITAL letters. Some examples are:

  • USER: The current logged in user.
  • HOME: The current user's home directory.
  • HOSTNAME: The hostname of the computer at this time.
  • TERM: This specifies the type of terminal to emulate when running the shell.
  • MAIL: The path to the current user's mailbox.

User variables are ones you create inside your script specifically for your script and the cannot be accessed outside your script.

Never name your user/private variables using UPPERCASE characters. Uppercase variable names are reserved for internal shell variables, and you run a risk of overwriting them.

We can create a backup script which will backup the users home directory to /tmp/.

#!/bin/bash

# This bash script is used to back up a user's home directory to /tmp/.

{{< highlight bash "linenos=table" >}}user=$(whoami) input=/home/$user output=/tmp/${user}_home_$(date +%Y-%m-%d_%H%M%S).tar.gz tar -czf $output $input echo "Backup of $input completed!"{{< / highlight >}}

In this example, we can see that the user variable "user" has been used to capture the output from the whoami command. It is then appended to a string and assigned to the input variable. An output variable is then created which again does some string concatenation and formatting of dates.

Using variables like this makes scripts easier to write, read and maintain.

Finally, the command takes in the variables instead of one really long line which is difficult to read as it will probably span multiple lines.

Parameters and User Input in Bash Scripts

Scripts can take in a series of parameters from the user, for example, a filename or path.

In the command line parameters are added after the script name and are separated with a space.

Here is a simple bash script to show parameters read in and shown on the screen.

{{< highlight bash "linenos=table" >}}#!/bin/bash echo $1 $2 $3{{< / highlight >}}

When run using script.sh aaa bbb ccc it will automatically assign 'aaa' to the variable $1, 'bbb' to $2 and 'ccc' to $3. You can then use these like any other variable.

Functions in Bash Scripts

Functions are small reusable blocks of code which perform one specific action. They can be called from multiple locations and prevent code duplication.

Functions in bash scripts are very similar to functions in other programming languages.

{{< highlight bash "linenos=table" >}}#!/bin/bash showMessage function showMessage() { echo "Hello World" }{{< / highlight >}}

You can also pass parameters into function in the same way parameters are passed into a function

{{< highlight bash "linenos=table" >}}#!/bin/bash showMessage "Hello World" "This is a message" function showMessage() { echo $1 echo $2 }{{< / highlight >}}

If...Else...Conditional Statements in Bash Scripts

Sometimes it is necessary to check a condition before running a section of code, or running one bit of code in certain circumstances and another in a different set of circumstances.

A basic if statement effectively says, if a particular condition is true, then perform a given set of actions.

{{< highlight bash "linenos=table" >}}#!/bin/bash if [ $1 -gt 100 ] then echo That\'s a large number. fi{{< / highlight >}}

When running this script and passing in a number, if the number is greater than 100 the script will output "That's a large number".

We can extend this to cover numbers less than 100 with a different message.

{{< highlight bash "linenos=table" >}}#!/bin/bash if [ $1 -gt 100 ] then echo That\'s a large number. else echo That\'s a small number. fi{{< / highlight >}}

Now if a number less than 100 is entered it will show "That's a small number".

We can also check another possibility, the user entered 100, and show another different message. In bash scripts, elif is short for else if.

{{< highlight bash "linenos=table" >}}#!/bin/bash if [ $1 -gt 100 ] then echo That\'s a large number. elif [ $1 -lt 100 ] echo That\'s a small number. else echo You entered 100. fi{{< / highlight >}}

Maybe you need to check multiple conditions using boolean operators.

{{< highlight bash "linenos=table" >}}if [ $USER == 'tim' ] || [ $USER == 'lonewolf' ] then ls -alh else ls fi{{< / highlight >}}

Looping and Iteration in Bash Scripts

Looping is very useful in any programming language. It lets you run a series of commands multiple times, usually over a collection of objects, for example, running a command for every file in a directory.

There are several different types of loop, I won't go into detail as to which one does what and when you should use one or the other. You can read more about looping in the article below.

{{< aside 624 >}}

While loop in Bash Script

The while loop is the easiest loop and works by evaluating a condition, similar to an if statement above, and if true runs a block of code. If the condition is still true it will run the code again, over and over, until the condition is false.

The basic syntax for a while loop is shown below. It will output the numbers 1 through 10 on the screen.

{{< highlight bash "linenos=table" >}}#!/bin/bash # Basic while loop counter=1 while [ $counter -le 10 ] do echo $counter ((counter++)) done{{< / highlight >}}

It is important to remember that the condition must always evaluate to false at some point, otherwise, you will have an infinite loop. If you forgot to increment the counter in the loop above, the system would continue to count on the screen until it broke the system.

For loop in Bash Script

For loops are a little harder to write, but they are more flexible and there is much less chance that you will have an infinite loop.

The same counting script using a for loop is below. It's less code but harder to read if you're unfamiliar with the syntax.

{{< highlight bash "linenos=table" >}}for value in {1..10} do echo $value done{{< / highlight >}}

For loops can work on collections of anything, for example, an array of names.

{{< highlight bash "linenos=table" >}}#!/bin/bash # Basic for loop names='Brando Hopkins Caine' for name in $names do echo $name done{{< / highlight >}}

Useful Bash Scripts

Here is a collection of some of my most useful bash scripts which you can download and use on your system.

Bash Script for Backup Files

This is my bash script for backing up my home NAS. It will first mount a USB3 external hard drive to /media/backup, then it will use rsync to backup the main NAS files, my home directory, apache and mysql directories. Finally it will run a mysqldump to backup my databases.

{{< highlight bash "linenos=table" >}}#!/bin/bash sudo mount -t ext4 /dev/sdf1 /media/backup sudo rsync -av /media/megadrive/files /media/backup/files sudo rsync -av /home/timmy /media/backup/timmy sudo rsync -av /etc/apache2 /media/backup/apache sudo rsync -av /var/lib/mysql /media/backup/mysql/data sudo mysqldump -uroot -p<password> mastersystem | bzip2 -c > /media/backup/mysql/$(date +%Y-%m-%d-%H.%M.%S).sql.bz2{{< / highlight >}}

Extract for all file types

This script will detect the file format of an archive and run the appropriate command to extract the files.

{{< highlight bash "linenos=table" >}}#!/bin/bash if [ -f $1 ] ; then case $1 in *.tar.bz2) tar xvjf $1 ;; *.tar.gz) tar xvzf $1 ;; *.tar.xz) tar Jxvf $1 ;; *.bz2) bunzip2 $1 ;; *.rar) rar x $1 ;; *.gz) gunzip $1 ;; *.tar) tar xvf $1 ;; *.tbz2) tar xvjf $1 ;; *.tgz) tar xvzf $1 ;; *.zip) unzip -d `echo $1 | sed 's/\(.*\)\.zip/\1/'` $1;; *.Z) uncompress $1 ;; *.7z) 7z x $1 ;; *) echo "don't know how to extract '$1'" ;; esac else echo "'$1' is not a valid file!" fi{{< / highlight >}}

Go Up Directory Tree

This little script is useful for directory navigation. Say you are in a deep directory, for example, /media/megadrive/wwwroot/public_html/lonewolfonline/wp-content/themes/lonewolf/css and you wanted to go back to the root of public_html you would either have to cd ../../../.. or you can use this to go up 4 (if you name the script up).

{{< highlight bash "linenos=table" >}}#!/bin/bash LIMIT=$1 P=$PWD for ((i=1; i <= LIMIT; i++)) do P=$P/.. done cd $P{{< / highlight >}}

Bash Script to Remove Empty Directories

This bash script will scan and remove empty directories.

{{< highlight bash "linenos=table" >}}#!/bin/bash [ $# -lt 1 ] && set -- . find "$@" -type d -depth -print | while read dir do [ `ls "$dir" | wc -l` -lt 1 ] || continue echo >&2 "$0: removing empty directory: $dir" rmdir "$dir" || exit $? done exit 0{{< / highlight >}} {{< series_footer 6755>}}

Leave a Reply

Fields marked with * are mandatory.

We respect your privacy, and will not make your email public. Hashed email address may be checked against Gravatar service to retrieve avatars. This site uses Akismet to reduce spam. Learn how your comment data is processed.