This post is part of a larger series on RHCSA

Conditionally execute code (use of: if, test, [], etc.)

test

The absolute heart of conditionals in bash is a program called test. You can view the man pages for test to get documentation on all the valid comparisons you can make.

When test makes a comparison, it counter-intuitively returns exit code 0 (success/no error) for true and exit code 1 for false. It sticks with exit code conventions at the sacrifice of boolean value conventions. The below examples demonstrate various comparisons made with test, at the end of each example we check the error code with echo $?.


# Is 1 greater than 100?
# Output: 1
test 1 -gt 100
echo $?

# Is 1 less than 100?
# Output: 0
test 1 -lt 100
echo $?

# Is "a string" equivalent to "a string"?
# Output: 0
test "a string" = "a string"
echo $?

# Does the file/directory "/home/steven" exist?
# Output: 0
test -e /home/steven
echo $?

Bash wraps conditional expressions in square brackets [ EXPRESSION ]. The square brackets in bash are actually a reference to the program called test. This completely blew my mind. The square brackets must be separate arguments. [-d /] is not the same as [ -d / ].

To see all comparisons you can make with test, read the man pages for test.

if

Test can be combined with the if statement so that it may be used for control flow.


# Outputs: 1 is smaller than 100.
if [ 1 -gt 100 ]; then
    echo "1 is greater than 100 - that's wrong!"
elif [ 1 -eq 100 ]; then 
    echo "1 equals 100 - that's wrong!"
else
    echo "1 is smaller than 100."
fi

Use Looping constructs (for, etc.) to process file, command line input

while

A while loop will continually run a section of script between do and done as long as the expression is true.

while [ EXPRESSION ]; do
    command
done

until

Conversely, you can use an until loop to do the same until the expression is not true.

until [ EXPRESSION ]; do
    command
done

for

““The mac-daddy of all loops.” - Steven Polley” - Steven Polley. Yes I just quoted myself quoting myself.

A for loop will assign item to the value in a space-delimited list of items. It’s written in the following basic format

for item in LIST; do
    command
done

Some examples are below:

# Outputs: 
# steven is the name in this iteration!
# mandi is the name in this iteration!
# phoebe is the name in this iteration!
for name in steven mandi phoebe; do
    echo $name is the name in this iteration!
done

# You can also specify a number range and bash will expand it

# Outputs: 0 1 2 3
echo echo {0..3}

# Outputs:
# 0 is the number!
# 1 is the number!
# 2 is the number!
# 3 is the number!
for i in {0..3}; do
    echo $i is the number!
done

Process script inputs ($1, $2, etc.)

Within a bash script, you can access values of arguments using the symbols shown in the table below.

SymbolMeaning
$0name of current program/file
$1First argument
$2Second argument
$3Third argument
$4Fourth argument
$@All arguments starting from first
$#Number of arguments

Here’s some examples:

# Create a test script to demonstrate handling script inputs
echo '#!/bin/bash

echo "The program name is $0"
echo "The first argument is $1"
echo "All arguments: $@"
echo "Number of arguments: $#"
' > argscript.sh

# Make the test script executable
chmod +x argscript.sh

# Run the test script with some example arguments
# Output:
# The program name is ./argscript.sh
# The first argument is firstarg
# All arguments: firstarg secondarg thirdarg wow this is a lot of arguments
# Number of arguments: 10
./argscript.sh firstarg secondarg thirdarg wow this is a lot of arguments

Processing output of shell commands within a script

You can use something called command substitution to run a command and use it’s standard output in place.

# Create a file full of words called words
echo apple banana orange and why not cake too > words

# Use command substitution in a loop.  
for word in $(cat words); do
    echo this word is $word
done

Technically $(< words) is superior than cat, but this is for demonstration purposes.