Skip to content

Flow Control#

Now that we understand variables and functions, we'll upgrade out initial script to use an if statement.

If#

Here's the upgraded version:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash

yourname=$1

if [ -z $yourname ]
then
  yourname="reader!"
fi

hello() {
  echo "Hello"
}

world() {
  echo "world"
}

hello
world

echo "$(hello), $(world)! My name is ${yourname}"

We've added in a new piece of functionality (and removed all the comments to reduce the reading):

1
2
3
4
if [ -z $yourname ]
then
  yourname="reader!"
fi

If is an if statement, and it's used a form of flow control. It can "control" the "flow" of your code because you can make branching decisions depending on whatever logic you desire. If in our code, we're changing the value inside of the $yourname variable in the event it's empty or zero (-z).

Now if we execute the script in multiple different ways, we get slightly different results:

1
2
3
4
5
6
7
8
9
$ bash script_example_3.sh
Hello
world
Hello, world! My name is reader!

$ bash script_example_3.sh Michael
Hello
world
Hello, world! My name is Michael

In the first output, we can see I didn't provide a string to the $1 argument (remember that $0 is the name of the script we executed.) Because we didn't provide a value, $yourname equals "", or an empty string. In our if statement we're testing to see if the string is empty: if [ -z $yourname ]. In English, this test is asking, "If the value inside of the variable $yourname is empty?". If it is, then the code inside of the if statement's body (which is everything between then and fi, which is if backwards) is executed.

In the second execution we did provide a string - Michael - so that means $1 wasn't empty, and so $yourname also wasn't empty. The if statement didn't execute, and the value inside of $yourname was not set to reader!.

Alternative syntax#

You may also see the above if statement written slightly differently:

1
2
3
if [ -z $yourname ]; then
  yourname="reader!"
fi

Note the use of ; and the then being present on the same line. The end result is the same and just a matter of preference when it comes to shell scripts inside of files, but...

You can use if statements on the command line too - outside of files. Like this:

1
2
3
4
5
$ yourname=""; if [ -z $yourname ]; then yourname="reader!"; fi; echo $yourname
reader!

$ yourname="Michael"; if [ -z $yourname ]; then yourname="reader!"; fi; echo $yourname
Michael

You can see the use of ; here is so that we can use all the statements on the same line. Even after the fi was use a semi-colon (;).

Does this mean we could do the same thing inside of our script? Yes. Check it out:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#!/bin/bash

yourname=$1

if [ -z $yourname ]; then yourname="reader!"; fi

hello() {
  echo "Hello"
}

world() {
  echo "world"
}

hello
world

echo "$(hello), $(world)! My name is ${yourname}"

The end results are the same!

Else#

So if we can perform a logical test, what happens if it's not true? Can we perform a test and do something if it's true or not true? Of course!

Let's upgrade our if statement (and change the format back to by multiple lines):

1
2
3
4
5
6
if [ -z $yourname ]
then
  yourname="reader!"
else
  echo "Thanks for providing a name :-)"
fi

And the result:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ bash script_example_3.sh
Hello
world
Hello, world! My name is reader!

$ bash script_example_3.sh Michael
Thanks for providing a name :-)
Hello
world
Hello, world! My name is Michael

So we can, essentially, say "if this, then do that; else do this instead".

Changing direction#

We're able to do more with the if statement than simply changing the value inside of a variable. We can completely change direction inside of our code! Let's change our code to demonstrate this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/bin/bash

yourname=$1

default_name() {
  yourname="reader!"
}

nondefault_name() {
  echo "Thank you for providing a name :-)"
}

if [ -z $yourname ]
then
  default_name
else
  nondefault_name
fi

hello() {
  echo "Hello"
}

world() {
  echo "world"
}

hello
world

echo "$(hello), $(world)! My name is ${yourname}"

And the end result is the same, again:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$ bash script_example_3.sh Michael
Thank you for providing a name :-)
No seriously... thanks for providing a name. Much appreciated.
Hello
world
Hello, world! My name is Michael

$ bash script_example_3.sh
Hello
world
Hello, world! My name is reader!

Except now we've used a set of new functions and changed our if/else statement to call them:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
default_name() {
  yourname="reader!"
}

nondefault_name() {
  echo "Thank you for providing a name :-)"
}

if [ -z $yourname ]
then
  default_name
else
  nondefault_name
  echo "No seriously... thanks for providing a name. Much appreciated."
fi

Note

The functions must be defined before you can call them. That's why they're defined above the if statement in the file.

And I've demonstrated that the body of code provided inside the if/else statement can also include multiple lines of code by adding in an extra echo statement that's probably over doing things a bit, but oh well.

This is a simple introduction to programming, so we'll leave the if statements there and look at a simple loop.