How To Create A Bash Script, With Example Code

With bash scripts, you can run sequences of commands. They prevent you from repeating yourself and allow you to store long and tedious to type commands for later usage. In this article, you’ll learn how to create a Bash script. You’ll also learn how to read arguments, use variables, and create for-loops to repeat actions.

Before you start creating scripts, make sure you are familiar with the basic Linux commands.

Create a Bash script

A command-line script starts with the shebang — a sequence of the two characters #!. After these two characters, you can name any interpreter and a bunch of arguments, like this:

#!interpreter [optional arguments]

A shell script is usually based on the most popular shell called Bash, so this would simply become:

#!/bin/bash

Sometimes you’ll see this instead:

#!/usr/bin/env bash

When using /usr/bin/env, the provided command will be searched for in the current $PATH, instead of hardcoding it to the /bin/bash location. Bash will almost always be found at /bin/bash, so the first method is fine for us.

However, you may want to use this trick to create an executable Python script. Python can be installed anywhere, depending on the way it is installed. I’ve seen it in /usr/bin//bin, and /usr/local/bin, just to name a few. If you’re running a virtual environment, it can be anywhere. So searching the $PATH is a good option, since that will find the Python version from the virtual environment.

We’ll get to creating an actual shell script in a moment. But first, we’ll take a look at variables and for-loops to juice things up a little.

Bash variables

Just like other languages, Bash has variables. One peculiar thing about variables in Bash is that you access them with the dollar sign, but you set them without it. To clarify, here’s an example:

myvar="Hello world"
echo $myvar

Bash has a number of reserved variables, that are automatically set for you. The following table is a non-exhaustive list of some of the more useful ones:

VariableFunction
$0Name of the current script.
$1 … $9First 9 arguments to the script.
$#Number of arguments passed to the script.
$@All the arguments supplied to the script.
$USERThe username of the user running the script.
$HOSTNAMEThe hostname of the machine the script is running on.
$SECONDSThe number of seconds since the script was started.
$RANDOMReturns a different random number each time is it referred to.
$LINENOReturns the current line number in the Bash script.
Bash reserved variables

Bash Script arguments

We’re now able to create a shell script, but this script will do the same thing each time you run it. We can make it infinitely more interesting by using arguments.

Here’s an example, call it arguments.sh:

#!/bin/bash
echo "Hello $1, from $0"

If we run this with one argument, the result is as follows:

$ ./arguments.sh Weirdo
Hello Weirdo, from ./arguments.sh

What Bash does, is chop up your entire command and assign it to the not very imaginative variables $0$1$2, et cetera. As you can see, the first part of our command is the name of the script itself. This can come in handy, as can be seen in the next section.

Create a safety net

Before moving on to the serious stuff, I want to teach you about an important safety net.

Once you start creating scripts, you will inevitably make mistakes. We all do. One very common mistake in scripts can be especially disastrous. It’s the unset variable. If you don’t know what I mean, just keep reading as it will become clear in a moment.

We can prevent using unset variables by starting our scripts with the following command:

set -u

That’s all! From here on, your script is treating unset variables as an error when you are substituting.

For example, this script will fail:

#!/bin/bash
set -u
rm -rf /$my_directory

The output:

$ ./test.sh                                                          
./test.sh: 3: ./test.sh: my_directory: parameter not set

That’s because I never set $my_directory. Without set -u, it won’t fail but instead just ignore the empty variable, leaving us with the command rm -rf /. We all know what that does, right? If executed by a privileged user (like root), this mistake would have wiped my entire filesystem instead of the directory I intended to delete.

Make a habit of always starting your scripts with set -u.

Bash for loop

The usefulness of the command-line, and especially scripts, increases exponentially once you master Bash for-loops. And even though they might look scary, they are really not that hard.

Syntax of a Bash for-loop

The basic syntax of a loop is:

for VARIABLE in A LIST
do
  command1
  command2
  commandN
done

Example Bash script

The A LIST part can be anything: file names, numbers, or strings. It will be a list of file names in most scripts, though, since that’s what we’re often working with in Bash. Now that we know how to create a loop, let’s look at our first script:

#!/bin/bash

echo "You can list numbers and text like this:"

for n in 1 2 3 four
do
  echo "Number $n"
done

echo "Or specify a range of numbers:"

for n in {1..5}
do
  echo "Number $n"
done

echo "Or use the output of another command:"
for f in $(ls)
do
  echo $f
done

In the last for-loop, I used the expression $(ls). This executes the command between parentheses and substitutes the result. In this case, ls gets executed and the for-loop is fed with the file names that ls prints out.

Starting a Bash script

To start this script, we can do two things. First, we can run it with:

$ bash loop.sh

The second way, that I recommend, is making the file executable. The OS will know how to execute our file because of our shebang line at the top! Making the file executable is done by setting the file’s “execute flag” like this:

$ chmod +x loop.sh

You can now run the script with:

$ ./loop.sh

The output in my case is:

$ ./loop.sh
You can just list a bunch of numbers and text like this:
1
2
3
four
Or specify a range of numbers:
1
2
3
4
5
Or use the output of another command:
loop.sh
notes.txt

It might differ for you, depending on which files are in the directory that you’re running the script in.

Bash conditional programming

Sometimes you only want to run a command if a certain condition is true. For this, we have the if… then… else…fi construct in bash.

Check arguments in bash script

We can use conditional programming to improve our previous example, arguments.sh, since it contained a little problem. It expects a name in $1 without checking if it actually gets one. Let’s fix this:

Check arguments in your Bash script

If that didn’t work, here’s a static version of the same code:

#!/bin/bash
if test -z "$1"
then
  echo "Usage: $0 <Your name>"
else
  echo "Hello $1, from $0"
fi

The test command in bash

With test -z we can check if a variable’s length is zero. If that is the case, we print some friendly usage instructions:

$ ./arguments.sh
Usage: ./arguments.sh <Your name>

The test command can test for many things so it really aids in conditional programming. The full list can be seen when you enter man test on the command line. That’s right, you don’t need Google for everything! Using man-pages is part of being a command-line ninja! You’ll find that there’s a man page for pretty much everything you can do in your terminal. After all, in the old days, we didn’t have the Internet to google everything…

Here is one more example in which we compare two values to see if they are the same:

Compare two values in Bash

Here’s the static version in case that didn’t work:

#!/bin/bash
for i in {1..10}
do
  if test $i -eq 3 
  then
    echo "I found the 3!"
  else
    echo "Not looking for the $i"
  fi
done

This loop runs for 10 iterations and checks if $i is equal to 3 each time. Can you predict the output?

Although the else-part is optional, you always need to end with a fi.

Get certified with our courses

Learn Python properly through small, easy-to-digest lessons, progress tracking, quizzes to test your knowledge, and practice sessions. Each course will earn you a downloadable course certificate.

Related articles

Leave a Comment