Linux: Automated Tasks with Shell Scripting
Parameter Expansion
Parameter Expansion
is a way to substitute the value of a variable into a command or script os that the instructions become dynamic and flexible instead of static. ex: ${var}
${var}
${var}
is used in shell environments to insert the value of a variable into a command. var
is the name of the variable we want to expand.
ex:
location="/var/log"
cd ${location}
Command Substitution
Command Substitution
inserts the result of a command directly into another command or script.
'bar'
- Single-Quoted String
Everything in the single quote is treated as literal text. There will be no variable expansion and no command substitution. The text will be printed as it is written.
ex:
echo 'Warning: $PATH cannot be found'
Warning: $PATH cannot be found
$(bar)
- Substituting a Command
This is how command substitution is done. This will run the command inside the parentheses by replacing the $(...)
with the command's output.
# /backup/YYYY-MM-DD
mkdir /backup/$(date +%F) # mkdir /backup/2025-11-15
Subshell Execution
A subshell
is a separate child process created by the shell to execute a command or group of commands in isolation without affecting the current shell environment. What ever happens inside the subshell will not carry over to the main shell session.
(bar)
- Creating a Subshell
The syntax is (cmd1; cmd2;...)
. All commands inside the parentheses are executed in a child shell.
ex:
# execute the command in a new shell
(bar)
Functions
A function
is a set of commands packaged under a single name to allow repeated use without rewriting the commands each time.
ex:
function hello {
echo "Hello, $1"
}
hello() {
echo "Hello, $1"
}
Bash functions can only return numeric exit codes.
Variables by default are global. Use local
to define a local variable in functions.
ex:
# to define a local variable in a function
function hello {
local my_var="Hello"
}
Internal Field Separator / Output Field Separator
IFS tells the shell where to split input into distinct words.
OFS is a tool used to re-assemble data for output.
Avoiding Word Splitting
Word Splitting
is the shell's habit of treating spaces, tabs, and newline inside a variable as natural break-point. To fix this, we wrap the variable in double quotes or pass it through printf
. ex: printf '%s\n' "$variable"
.
With
file_path="My project/file.txt
cat file_path
the shell will attempt to open 2 files: My
and project/file.txt
.
But printf '%s\n' "$file_path"
will produces the exact string, in one line, with no splits.
Controlling Input Splitting
IFS=<DELIMITER> read -r VAR1 VAR2,... <<< "$TEXT"
ex:
IFS=',' read -r name city role <<< "tome,New York,Developer"
Output Formatting
A common pattern is awk 'BEGIN{OFS="<DELIMITER>"} {print $1,$2,...}' <FILE>
ex:
# converting a portion of /etc/passwd file into a CSV
awk 'BEGIN{OFS=","} {print $1,$3,$4}' /etc/passwd | head -n 3
BEGIN{OFS=","}
tells awk
that commas should go between fields.
$1, $3, and $4
refers to the username
, uid
, and gid
columns respectively.
Conditional Statements
if
It is used for running a single yes
or no
task like:
-
Verifying a service is running
-
Checking free disk space
-
Making sure a variable isn't empty
if condition; then
commands
elif another_condition; then
commands
else
commands
fi
# to check for a file
location="/var/log/auth.log"
if [[ -f $location ]]; then
echo "$location exists"
elif [[ -d $location ]]; then
echo "$location is a directory"
else
echo "$location does not exist"
fi
Options include:
-
-f
for a file -
-d
for a directory -
-z
for a string -
-eq
numeric equal -
-ne
numeric not equal -
-lt
numeric less than -
-gt
numeric greater than -
=
string equal -
!=
string not equal
case
A case
statement is used when a variable can take several acceptable values, or answers, and needed different actions for each.
case expression in
pattern1)
commands ;;
pattern2|pattern3)
commands ;;
*)
commands ;; # default case
esac
echo "Select an option: start | stop | restart"
read action
case $action in
start)
echo "Starting service..." ;;
stop)
echo "Stopping service..." ;;
restart|reload)
echo "Restarting service..." ;;
*)
echo "Unknown option: $action" ;;
esac
$1
is a positional parameter. It means it automatically holds the first command-line argument that was supplied when the script was launched.
Looping Statements
Loops allow a program to repeat actions automatically without rewriting the same instructions repeatedly.
for
for
loop repeats a task a specific number of times of for each item in th a list.
ex:
for fruit in orange apple banana
do
echo "fruit: $fruit"
done
while
while
loop continues running as long as a condition remains true. A while loop is great when you do not know how many times something should repeat.
counter=1
while [ $counter -le 5 ]
do
echo "count is $counter"
((counter++))
done
until
until
runs until a condition becomes true.
counter=1
until [ $counter -ge 5 ]
do
echo "count is $counter"
((counter++))
done
Interpreter Directive
An interpreter directive
is a special line at the very top of the file that tells the system which program should be used to interpret the commands that follow.
It start with #!
called shebang
followed by the path of the interpreter like /bin/bash
.
For bash script, we typically use #!/bin/bash
ex:
hello.sh
#!/bin/bash
echo "hello world"
Numerical Comparisons
-
-eq
equal to -
-ne
not equal to -
-lt
less than -
-le
less than or equal to -
-gt
greater than -
-ge
greater than or equal to
They are always used in []
when making comparisons.
result=8
if [ "$result" -lt 5 ]; then
echo "Less than 5"
elif [ "$result" -eq 5 ]; then
echo "Equal to 5"
else
echo "Greater than 5"
fi
Redirection String Operators
>
redirection operator
>
redirects outputs to a file. It creates the file automatically if it does not exist or overwrite its content if it exists.
echo "Operation completed with code 0" > result.txt
<
redirection operator
<
takes input from a file.
read value < input.txt
Comparison String Operators
'String comparison operators check whether two pieces of text are the same, different, match a pattern or follow a certain alphabetical order.
==
and=
for comparing if two strings are equal!=
for checking if two strings are not equal=~
for matching patterns using regular expressions<=
and>=
for comparing string alphabetical order
==
, =
, and =~
==
is typically used inside double square brackets ([[]]
) and is read as is equal to
.
=
is used inside single square brackets ([]
) and is read simply as equals
.
=~
is used for more advanced comparison.
#!/bin/bash
text="Hello"
if [[$text == "Hello"]]; then
echo "Text is exactly Hello"
fi
if [[$test =~ ^H]]; then
echo "The test start with H"
fi
!=
#!/bin/bash
result="completed"
if [$result != "completed"]; then
echo "The task completed successfully"
fi
<=
and >=
This is a Lexicographical Comparison
. Bash checks which string would come first or last in alphabetical order.
<=
is read as is less than or equal to
>=
is read as is greater than or equal to
#!/bin/bash
fruit="papaya"
if [[$fruit >= "mango"]]; then
echo "$fruit comes after or is equal to mango"
fi
if [[$fruit <= "melon"]]; then
echo "$fruit comes before or is equal to melon"
fi
Regular Expressions
A regex
is a special sequence of characters that defines a search pattern.
Bash uses =~
inside [[]] to match patterns with regular expression ([[ $variable =~ pattern]]
).
#!/bin/bash
data="234567"
if [[ $data =~ ^[0-9]+$ ]]; then
echo "The data contains only numbers"
fi
Test Operators
Test operators
are special symbols used to evaluate things like file existence, string content, and logical conditions. They return either true or false.
-d
and -f
-d
and -f
are operators used in scripts to check whether something exists on the filesystem and whether it's is a directory or a regular file.
#!/bin/bash
if [ -d "project" ]; then
echo "the project folder is a directory"
fi
if [ -f "app.conf" ]; then
echo "app.conf is a file"
fi
-n
and -z
-n
and -z
are string test operators. They help check whether a string has a value or is empty, which is especially useful when dealing with user input.
#!/bin/bash
input=""
if [ -z "$input" ]; then
echo "The input is empty"
fi
input="hello"
if [ -n "$input" ]; then
echo "the input is not empty"
fi
!
!
is the logical negation operator.
#!/bin/bash
if [ ! -f "config.txt" ]; then
echo "config file does not exist"
fi
Variables
Variables are used to store and work with information like text, numbers, or user input.
Positional Arguments
Positional arguments are values passed to a script when running it, allowing the script to respond to user input. The first argument is $1
, the second is $2
and so on.
#!/bin/bash
if [ $1 -gt 5 ]; then
echo "The number is greater than 5"
else
echo "The number is less than or equal to 5"
fi
# then run the script
./script.sh 10
Environment Variable
Environment variables are built-in variables provided by the system or user that store important information.
Built-in variables:
$USER
: username$HOME
: home directory$SHELL
: current shell
#!/bin/bash
if [ $USER = 'root' ]; then
echo "You are logged in as the root user"
else
echo "You are logged as regular user $USER"
fi
Alias and Command Management
alias
alias
command creates shortcuts for longer commands. The generic syntax is alias name='command'
.
Aliases set in the terminal are only temporary and only last for that session.
# create a shortcut called ckdsk
alias ckdsk='df -h'
unalias
unalias
command removes shortcuts that was previously created.
# to remove a previously created alias
unalias ckdsk
set
set
modify the behavior of the shell.
#!/bin/bash
# to stop script from running if any command inside it fails
set -e
echo "running system update..."
sudo dnf update
echo "update completed"
Other options with set
:
-x
prints each command before it is executed-u
exits script when attempting to use an undefined variable-o pipefail
makes a pipeline fail if any command in the pipeline fails
Variable Management
export
allows a variable to be passed to child processeslocal
restricts a variable's scope to within a functionunset
deletes a variable
export
export
is used to make a variable available to child processes, such as a subshell or another script that is launched from the current shell. The syntax is export VARIABLE=value
export LOG_LEVEL=debug
./myscript.sh # run in a separate shell process bt still has access to LOG_LEVEL because of 'export'
local
local
command is used to restrict variable to within a function. The syntax is local VARIABLE=value
unset
unset
is used to remove a variable. The syntax is unset VARIABLE
log_file="log.txt"
echo "processing file"
unset log_file
Return Codes
A return code
or exit status
is a number left behind after a command or program finishes in Linux to indicate success or failure.
$?
is used to see the exit code of the last command.
0
means successNon-zero
means error