Moving Forward With Bash Scripting
Moving Forward With Bash Scripting
Comments in Bash:
• Like in other programming languages, you can add comments to your script
to leave notes.
• Use the # symbol at the beginning of a line to add a comment; it won’t display
on the screen.
• Example:
- Bash Arguments:
• Pass arguments to your shell script by writing them after the script name.
• Access arguments using $1, $2, etc. within the script.
• Access count of the arguments by #
• Example:
[[ -a ${file} ]]
[[ -b ${file} ]]
[[ -c ${file} ]]
[[ -d ${file} ]]
[[ -e ${file} ]]
[[ -f ${file} ]]
[[ -h ${file} ]]
[[ -L ${file} ]]
[[ -r ${file} ]]
• True if the file exists and has a size greater than zero.
[[ -s ${file} ]]
[[ -w ${file} ]]
[[ -x ${file} ]]
2
String expressions
• True if the shell variable varname is set (has been assigned a value).
[[ -v ${varname} ]]
[[ -z ${string} ]]
[[ -n ${string} ]]
[[ ${string1} == ${string2} ]]
[[ ${string1} != ${string2} ]]
Arithmetic operators
• Returns true if the numbers are equal
3
[[ ${arg1} -le ${arg2} ]]
• As a side note, arg1 and arg2 may be positive or negative integers. As with
other programming languages you can use AND & OR conditions:
[[ $? -eq 0 ]]
• returns true if the last command was not successful or had errors
[[ $? -gt 0 ]]
%%sh
if [ condition ]; then
# code block
else
# code block
fi
%%sh
#!/bin/bash
4
else
echo "Number is not greater than 10."
fi
Bash Conditionals
• Let’s revisit if/else statements and work with switch statements.
If Statement
• The if statement in Bash follows this structure:
if [[ some_test ]]
then
<commands>
fi
• For instance, consider this example prompting the user to input their name if
left empty:
#!/bin/bash
if [[ -z ${name} ]]
then
echo "Please enter your name!"
fi
if/else Statement
• With an if-else statement, you can define an action when the condition in
the if statement doesn’t match. Here’s an example incorporating conditional
expressions:
#!/bin/bash
if [[ -z ${name} ]]
then
echo "Please enter your name!"
else
5
echo "Hi there ${name}"
fi
• You can employ the above if statement with the conditional expressions dis-
cussed earlier, like this:
#!/bin/bash
admin="adam"
• Another example checks the current User ID and prevents script execution if
the user is root:
#!/bin/bash
• You can also test multiple conditions with an if statement. In this example,
we ensure the user is neither the admin nor the root user to prevent potential
damage:
#!/bin/bash
admin="adam"
• For more complex scenarios, you can use elif statements with if and else.
6
#!/bin/bash
case $some_variable in
pattern_1)
commands
;;
pattern_2| pattern_3)
commands
;;
*)
default commands
;;
esac
7
• Close the case statement with esac (case spelled backward).
• Consider this example of a Bash case statement:
– This script prompts the user to input a car brand name like Tesla, BMW,
Mercedes, etc. Then, based on the brand name, it prints out the factory’s
location. If the brand name doesn’t match any case statement, it prints
out a default message: an unknown car brand.
#!/bin/bash
case $car in
Tesla)
echo -n "${car}'s car factory is in the USA."
;;
*)
echo -n "${car} is an unknown car brand"
;;
esac
case $choice in
1) shutdown now
;;
2) shutdown –r now
;;
3) break
;;
*) continue
;;
8
esac
Excercises
1. Write a Bash program (w9ex1.sh) where you assign two numbers to different
variables, and then the program prints the sum of those variables.
2. Write another Bash program (w9ex2.sh) where you assign two strings to dif-
ferent variables, and then the program prints both of those strings. Write a
version where the strings are printed on the same line and a version where the
strings are printed on different lines.
3. Write a Bash program (w9ex3.sh) that prints the number of arguments pro-
vided to that program and prints the result of the multiplication of the first
argument with the number of arguments provided to the program.
4. Write a Bash program (w9ex4.sh) that asks for your first name and last name
and prints it.
5. Write a Bash program (w9ex5.sh) to greet the user, display the number of
running processes, and then list the processes along with their IDs.
6. Write a Bash program (w9e6.sh) that can create a random file name with
the current date and time in the current directory to store the uptime of the
computer.
7. Write two Bash programs (w9ex7 and w9ex8.sh) that will convert the decimal
to hexadecimal and hexadecimal to decimal, respectively.
8. Write a Bash program (w9ex9.sh) to return the size of the directory passed to
the program.
9. Write a Bash program (w9ex10.sh) to look at the CPU usage information from
/proc/stat filesystem and print it.
10. Write a Bash program (w9ex11.sh) to test a file, if is/or regular file, or a
directory or is readable or is writable or is executable/searchable.
11. Write a Bash program (w9ex12.sh) to use switch case statements to ask the
user the input to perform the mathematical operations.
Special characters
• [[ ]]: Test — an evaluation of a conditional expression to determine whether
it is “true” or “false”. Tests are used in Bash to compare strings, check the
existence of a file, etc. More advanced than [].
• ( ): Subshell group — similar to the above but where commands within
are executed in a subshell (a new process). Used much like a sandbox, if a
command causes side effects (like changing variables), it will not affect the
current shell.
• (( )): Arithmetic expression — with an arithmetic expression, characters
such as +, -, *, and / are mathematical operators used for calculations. They
can be used for variable assignments like (( a = 1 + 4 )) as well as tests like
if (( a < b )).
• $(( )): Arithmetic expansion — Comparable to the above, but the expression
is replaced with the result of its arithmetic evaluation. Example: echo “The
average is $(( (a+b)/2 ))”. The command let can also be used to evaluate the
expressions.
9
• { }: Inline group — commands inside the curly braces are treated as if they
were one command. It is convenient to use these when Bash syntax requires
only one command and a function doesn’t feel warranted.
Arrays
• Arrays in Bash are ordered lists of values.
• Lists are created with parentheses (( )) with a space separating each element
in the list.
• To retrieve elements of the array, you use parameter expansion: ${plagues[index]}.
• The positions of the elements in the array are numbered starting from zero.
• To get all elements of plagues, use a star (*) between the square brackets:
${plagues[*]}.
#!/bin/bash
plagues=(blood frogs lice flies sickness boils hail locusts
↪ darkness death)
echo ${plagues[0]} ## blood
echo ${plagues[3]} ## flies
echo ${plagues[*]} ## blood frogs lice flies sickness boils
↪ hail locusts darkness death
Arrays
• You can change individual elements in the array by specifying their index with
square brackets.
#!/bin/bash
plagues[4]=disease
echo ${plagues[*]} ## blood frogs lice flies disease boils hail
↪ locusts darkness death
• To get only part of an array, specify the index to start at and the number of
elements to retrieve, separated by colons.
• The length of an array can be found using the pound sign (#).
Arrays
• The plus-equals operator (+=) can be used to add an array onto the end of
another array.
#!/bin/bash
echo ${plagues[*]:5:3} ## boils hail locusts
echo ${#plagues[*]}
• The plus-equals operator (+=) can be used to add an array onto the end of
another array.
10
#!/bin/bash
plagues+=(illness)
echo ${#plagues[*]}
Braces
• Bash has a very handy tool for creating strings out of sequences called brace
expansion.
• Brace expansion uses the curly brackets and two periods ({ .. }) to create a
sequence of letters or numbers.
• For example, to create a string with all of the numbers between zero and nine,
you could do the following:
echo {0..9}
## 0 1 2 3 4 5 6 7 8 9
Braces
• In addition to numbers, you can also create sequences of letters:
echo {a..e}
echo {W..Z}
## a b c d e
## W X Y Z
• Strings can be placed on either side of the curly brackets, and they’ll be
“pasted” onto the corresponding end of the sequence:
echo a{0..4}
echo b{0..4}c
## a0 a1 a2 a3 a4
## b0c b1c b2c b3c b4c
Braces
• You can also combine sequences so that two or more sequences are pasted
together:
echo {1..3}{A..C}
## 1A 1B 1C 2A 2B 2C 3A 3B 3C
• If you want to use variables to define a sequence, you need to use the eval
command to create the sequence:
start=4
end=9
11
echo {$start..$end}
eval echo {$start..$end}
## {4..9}
## 4 5 6 7 8 9
Braces
• You can combine sequences with a comma between brackets ({,}):
echo {{1..3},{a..c}}
## 1 2 3 a b c
echo {Who,What,Why,When,How}?
## Who? What? Why? When? How?
Exercises
12. Write a bash script (w9ex13.sh) where you define an array inside of the script,
and the first argument for the script indicates the index of the array element
that is printed to the console when the script is run.
• Write a bash script (w9ex14.sh) where you define two arrays inside of the script,
and the sum of the lengths of the arrays are printed to the console when the
script is run.
• Write a bash script (w9ex15.sh) to create 100 text files using brace expansion.
• Loops are one of the most important programming structures in the Bash
language.
• They allow you to repeat lines of code based on logical conditions or by follow-
ing a sequence.
• The first kind of loop discussed is a FOR loop, which iterates through every
element of a specified sequence.
• Example FOR loop:
#!/bin/bash
for i in {1..3}
do
echo "i is equal to $i"
12
done
For Loop
• The following example illustrates creating sequences for FOR loops using an
explicit list, an array, and command substitution.
• Example with other sequence-generating strategies:
#!/bin/bash
echo ""
echo "Array:"
echo ""
echo "Command substitution:"
13
While Loop
Here’s the text bullet-pointed and followed by code examples explaining the con-
cept:
• Now that we’ve gotten a few FOR loops working, let’s move on to WHILE
loops.
• WHILE loops combine parts of the FOR loop and the IF statement.
• Example WHILE loop:
#!/bin/bash
count=3
While Loop
• The WHILE loop begins with the while keyword followed by a conditional
expression.
• As long as the conditional expression is true at the beginning of an iteration,
the code within the WHILE loop continues to execute.
• The variable $count is decremented by 1 in each iteration until it becomes 0,
ending the loop.
• Example of an infinite loop:
#!/bin/bash
count=3
while [[ $count -gt 0 ]]
do
echo "count is equal to $count"
let count=$count+1
done
• When executing this script, the loop runs forever because the condition [[
$count -gt 0 ]] is always true.
• Infinite loops can be terminated using Ctrl + C.
Nested Loops
• Nested loops: FOR loops can be nested within each other, as demonstrated
here:
#!/bin/bash
for number in {1..3}
do
14
for letter in a b
do
echo "number is $number, letter is $letter"
done
done
Nested Loops
• Example of nesting IF statement within a FOR loop:
#!/bin/bash
for number in {1..10}
do
if [[ $number -lt 3 ]] || [[ $number -gt 8 ]]
then
echo $number
fi
done
• The echo command is executed only if the value of $number is less than 3 or
greater than 8.
References
• https://seankross.com/the-unix-workbench/
• https://ebook.bobby.sh/
• https://github.com/ruanyf/simple-bash-scripts/tree/master
15