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.
Symbol | Meaning |
---|---|
$0 | name of current program/file |
$1 | First argument |
$2 | Second argument |
$3 | Third argument |
$4 | Fourth 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.