0% found this document useful (0 votes)
3 views47 pages

Lecture 5 Shell Scripting Essentials

The document is a comprehensive guide to mastering Bash shell scripting in Linux, covering topics from the basics of shell scripting to advanced concepts like control flow and file queries. It explains the structure of shell scripts, the use of variables, input/output handling, and various control flow constructs such as loops and conditionals. Additionally, it provides practical examples and best practices for writing effective scripts.

Uploaded by

bestdogames2
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views47 pages

Lecture 5 Shell Scripting Essentials

The document is a comprehensive guide to mastering Bash shell scripting in Linux, covering topics from the basics of shell scripting to advanced concepts like control flow and file queries. It explains the structure of shell scripts, the use of variables, input/output handling, and various control flow constructs such as loops and conditionals. Additionally, it provides practical examples and best practices for writing effective scripts.

Uploaded by

bestdogames2
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Shell Scripting Essentials

A comprehensive study guide for mastering Bash shell scripting in Linux — from your first script
to functions, arrays, and beyond.
CHAPTER 1

What Is Shell Scripting?


Understanding the foundation of automation in Linux environments
The Power of Shell Scripts
A shell script is a plain text file containing a series of commands written in the shell language. When executed, the script runs each command sequentially — just as
if you had typed them one by one into the terminal, but without the repetitive effort.

Shell scripts are far more than simple command lists. They support variables, control-flow constructs (such as if-then-else and loops), function definitions, and
mechanisms for input and output. If a task can be accomplished by combining existing Linux commands, writing a shell script is often the most efficient approach.

Scripts written by individual users can also become general-purpose tools. Such scripts are often installed in system directories accessible to all users on a
machine.
Two Ways to Run a Script
Before your script can do anything useful, you need to know how to invoke it. Bash provides two distinct methods for executing shell scripts, each suited to different
scenarios.

Explicit Interpretation Implicit Interpretation


You directly tell the system which shell interpreter to use: First, make the script executable:

bash [Link] [arg ...] chmod u+x [Link]

sh [Link] [arg ...] Then invoke it like any other command:

This approach works even if the file lacks execute permissions. ./[Link] [arg ...]

The system reads the shebang line to determine the interpreter.


Your First Shell Script
Every Bash script begins with a shebang line — a special directive that tells Linux which interpreter to use. The shebang is written as #! followed by the full path to
the interpreter.

#!/bin/bash
# This is a simple script to greet the user ([Link])
echo "Hello, welcome to the Linux shell scripting lab!"

1 Write the script 2 Make it executable 3 Run the script


Create a file called [Link] with the code Run chmod u+x [Link] to grant the Execute it with ./[Link] — you should see
above using any text editor such as nano or owner execute permission on the file. the greeting printed to your terminal.
vim.
Script Execution Rules
Inside a shell script, commands are executed sequentially from top to bottom. Each
command is separated by either a newline or a semicolon (;).

Comments are introduced with the # symbol. Anything after # on a line is ignored by
the interpreter — use comments generously to document your scripts.

Error handling: If a command fails during execution, the default behaviour is


to skip the offending command and continue with the next one. The script
does not halt automatically on errors.
CHAPTER 2

Variables in Bash
Storing, accessing, and manipulating data within your scripts
Three Types of Variables
Bash distinguishes between three categories of variables, each with a distinct purpose and scope. Understanding these categories is essential for writing effective
scripts.

1 2 3

Positional Parameters Environment Variables User-Defined Variables


Automatically set from command-line Created and maintained by the system. Written Created by you within a script. Any valid name
arguments: $0, $1, $2, and so on. Also includes in UPPERCASE, they control shell behaviour — starting with a letter or underscore is allowed.
special variables like $# and $*. examples include PATH, SHELL, DISPLAY, and Remember: variable names are case-sensitive.
LANG.
Positional Parameters Explained
When a Bash script is invoked, the shell automatically populates several special variables based on how the script was called and what arguments were passed.

$0 The name of the script itself (e.g. ./[Link])

$1, $2, $3… The first, second, third (and so on) command-line arguments

$# The total number of positional parameters passed

$* All arguments as a single string

$@ All arguments as separate quoted strings


Positional Parameters in Action
Consider the following script, saved as [Link]:

#!/bin/bash
## echoing Shell parameters
echo '$0 = '$0
echo '$1 = '$1
echo '$2 = '$2
echo '$3 = '$3
echo '$# = '$#
echo '$* = '$*
echo '$@ = ' $@

Running ./[Link] A B C D produces:

$0 = ./[Link]
$1 = A
$2 = B
$3 = C
$# = 4
$* = A B C D
$@ = A B C D

Notice that $# reports 4 because four arguments were passed — $0 (the script name) is not counted among them.
Environment Variables
What Are They? How to View Them
Environment variables are created and maintained by the Linux Bash shell To see all system environment variables, use either:
itself. They are always written in CAPITAL LETTERS and control how the
env
system and shell behave.
printenv
Common examples include PATH (the program search path), HOME (user's
home directory), LANG (locale settings), and HISTSIZE (command history To display a single variable's value:
length).
echo "$PATH"

This reveals the directories the shell searches when you type a command.
User-Defined Variables
You can create your own variables within a script to store data. The syntax is straightforward, but there is one critical rule to remember.

varName=someValue

No spaces around the equals sign! Writing varName = someValue with spaces will cause an error. The assignment must be written as
varName=someValue with no gaps.

To access the variable's value, prefix the name with a dollar sign: $varName or ${varName}. The curly brace notation is useful when the variable name needs to be
distinguished from surrounding text.

Valid Names Examples


Must start with a letter or underscore. Can contain letters, digits, and name="Alice"
underscores. Case-sensitive: myVar ≠ MYVAR. count=42
_flag=true
CHAPTER 3

Input & Output


Reading user input and working with the read command
The read Command
The read built-in command pauses script execution and waits for the user to type input. It then stores the entered words into one or more variables.

read -p "Prompt message: " variable1 variable2 variableN

The -p Flag Multiple Variables


Displays a prompt message to the user on the same line, without a newline. This If you supply multiple variable names, read splits the input by spaces: the first
keeps the input visually clean and intuitive. word goes into the first variable, the second word into the second, and so on.
Any remaining words go into the last variable.
Read Command — Worked Example
This script demonstrates how read distributes input across three variables:

#!/bin/bash
read -p 'Insert three values: ' a1 a2 a3
echo $a1 $a2 $a3
echo 'Good bye'

When you run ./[Link] and enter 1 2 3, the output is:

Insert three values: 1 2 3


123
Good bye

A simpler form reads a single value — perfect for interactive greetings or confirmations:

#!/bin/bash
read -p "Enter your name: " name
echo "Hello, $name!"
The shift Command
The shift command left-shifts all positional parameters. After shift, what was $2 becomes $1, $3 becomes $2, and so on. The original $1 is discarded. You can also
specify a count: shift n shifts by n positions.

#!/bin/bash
echo "Total arguments passed are: $#"
echo "The arguments are: $*"
echo "The First Argument is: $1"
shift 2
echo "The First Argument After Shift 2 is: $1"
shift
echo "The First Argument After Shift is: $1"

Running ./[Link] G1 G2 G3 G4 produces:

Total arguments passed are: 4


The arguments are: G1 G2 G3 G4
The First Argument is: G1
The First Argument After Shift 2 is: G3
The First Argument After Shift is: G4

shift is especially useful when you've processed the first few arguments and want to iterate over the rest with a loop.
CHAPTER 4

Control Flow
Branching and decision-making in your scripts
The if Command
The if construct is the primary tool for conditional execution in Bash. It evaluates a test
expression and runs different command lists depending on whether the result is true or false.

Simple Form

if test-expr
then
commandlist1
else
commandlist2
fi

If the test expression evaluates to true, commandlist1 executes. Otherwise, commandlist2


runs. The else clause is optional — you can omit it when no alternative action is needed.
Extended Branching with elif
When you need to test multiple conditions in sequence, the elif (else-if) construct provides a clean, readable structure without deep nesting.

if test-expr1
then
commandlist1
elif test-expr2
then
commandlist2
else
commandlist3
fi

The shell evaluates each condition from top to bottom. As soon as one test expression is true, its corresponding command list executes and the rest of the structure
is skipped. The final else block acts as a catch-all default.

Tip: You can chain as many elif blocks as needed, but if you find yourself using more than three or four, consider using the case command instead for
cleaner code.
The case Command
While if-elif-else handles general logical branching, the case command provides branching based on simple pattern matching. It compares a string against a series
of patterns and executes the command list for the first match.

case (str) in
pattern1) commandlist1 ;;
pattern2) commandlist2 ;;
esac

Pattern Matching When to Use Default Branch


Each pattern can include wildcards like * and ?. Use case when comparing a variable against a A trailing *) pattern acts as a catch-all default,
The double semicolons ;; terminate each branch fixed set of known values — for example, similar to else in an if statement.
— they are required. processing menu choices, file extensions, or
command-line flags.
CHAPTER 5

Loops & Iteration


Repeating commands efficiently with for, while, and until
The for Loop
The for command repeats a set of commands for each word in a given list. It is the most commonly used loop construct in Bash scripting.

Standard Form

for var in wordlist


do
commandlist
done

With each iteration, the control variable var takes the next word from the list as its value. You can also write it on a single line using semicolons:

for var in wordlist ; do commandlist ; done


C-Style for Loop
Bash also supports a C-language-style for loop, which is ideal when you need numeric iteration with an index counter.

#!/bin/bash
for (( i = 0 ; i < 9 ; i++ ))
do
echo $i
done

This prints the numbers 0 through 8. The three expressions inside the double parentheses work exactly like C: initialisation, condition, and increment.

1 2

Initialise Test Condition


i=0 i<9

3 4

Execute Body Increment


echo $i i++
The while and until Loops
In addition to for, Bash provides two more iteration constructs that loop based on an arbitrary condition rather than a fixed list.

while Loop until Loop


Executes the command list as long as the test expression is true. The condition The inverse of while — it loops until the test expression becomes true. The
is checked before each iteration. body executes as long as the condition remains false.

while test-expr until test-expr


do do
commandlist commandlist
done done

If the condition is false from the start, the body never executes. Useful when you're waiting for a specific condition to be met.
break and continue
These two commands give you fine-grained control over loop execution, allowing you to exit early or skip iterations selectively.

break
Immediately exits the nearest enclosing loop. Control jumps to the first line
after done. Use when a specific condition means the loop should stop
entirely.

continue
Skips the rest of the current iteration and jumps back to the top of the loop
for the next cycle. Use when certain iterations should be bypassed.

Example: break in Action

#!/bin/bash
for i in {1..5}; do
if [[ $i -eq 3 ]]; then
break
fi
echo "Current value of i: $i"
done
echo "Loop finished."

Output: prints values 1 and 2, then "Loop finished." — the loop exits when i reaches 3.
CHAPTER 6

File Queries
Testing file properties and permissions within your scripts
Querying File Status
Bash provides a rich set of conditions for checking file and directory properties. These file
queries follow the syntax -x file, where x is a single character that specifies the test to perform.
If the file does not exist or is inaccessible, all queries return false.

Practical Example

if [[ -f "$file" && -w "$file" ]]; then


cat "$1" >> "$file"
else
echo "access problem for $file"
fi

This snippet first checks that the file is a regular file (-f) and is writable (-w) before appending
content to it.
Complete File Query Reference
The table below summarises all essential file test operators in Bash. Memorise the most common ones — you will use them frequently in scripts that interact with
the filesystem.

Expr True if file… Expr True if file…

-r Is readable by the user -o Is owned by the user

-w Is writable by the user -s Has non-zero size

-x Is executable by the user -f Is an ordinary file

-e Exists -d Is a directory

Combining tests: Use && (AND) and || (OR) to combine multiple file queries within double brackets: [[ -e "$f" && -r "$f" ]].
CHAPTER 7

Arithmetic & Comparisons


Performing calculations and numeric tests in Bash
Numerical Expressions
Since all Bash variables are fundamentally string-valued, you need special syntax to perform integer arithmetic. Bash provides two mechanisms for this.

1 2

Arithmetic Expansion The let Command


Use the $(( )) notation to evaluate integer expressions inline. For example: The built-in let command evaluates arithmetic expressions. Usage: let
result=$(( x * y )). The expression is evaluated and the result replaces the z=$(( x * y )) or let "z = $((x/y))". Multiple expressions can be evaluated in
notation. one call.

Example

#!/bin/bash
x=10
y=3
let z=$(( x * y ))
echo $z # Output: 30
let "z = $((x/y))"
echo $z # Output: 3
Numeric Comparison Operators
When you need to compare numbers inside test expressions (e.g. within if statements), Bash uses special operator flags rather than the familiar symbols < and >.

Operator Description

arg1 -eq arg2 True if arg1 equals arg2

arg1 -ne arg2 True if arg1 is not equal to arg2

arg1 -lt arg2 True if arg1 is less than arg2

arg1 -le arg2 True if arg1 is less than or equal to arg2

arg1 -gt arg2 True if arg1 is greater than arg2

arg1 -ge arg2 True if arg1 is greater than or equal to arg2

These operators are used inside single brackets [ ] or double brackets [[ ]]. For example: if [[ $count -gt 10 ]]; then ...
CHAPTER 8

Quoting in Bash
Single quotes, double quotes, and backticks — knowing the difference matters
Understanding Quoting
Bash uses three distinct types of quotes, and confusing them is one of the most common
sources of scripting errors. Each type controls how the shell interprets the text inside.

Single Quotes ' ' Double Quotes " "


Everything between single quotes is Allow variable expansion and command
treated as a literal string. No variable substitution within the string. Special
expansion, no command substitution, no characters like $, `, and \ are still
special character interpretation occurs. interpreted.

Example: '$HOME' prints $HOME, not Example: "$HOME" prints /home/user.


the path.

Backticks ` `
Used for command substitution — the enclosed command is executed and its output
replaces the backticks. Modern syntax prefers $(command) instead.
CHAPTER 9

Arrays
Storing and manipulating collections of values
Creating and Using Arrays
Bash supports indexed arrays with zero-based indexing. Arrays allow you to store multiple values under a single variable name — essential when working with lists
of data.

Two Ways to Create

# Method 1: Assign all at once


fruits=("red apple" "golden banana")

# Method 2: Assign element by element


fruits[0]="red apple"
fruits[1]="golden banana"

Access Elements Array Length All Elements


${fruits[0]} returns the first element. Using just ${#fruits[*]} returns the total number of elements ${fruits[*]} or ${fruits[@]} expands to every
${fruits} without an index also returns the first in the array. element in the array.
element by default.
Array Operations
Bash arrays support several useful operations beyond simple access. Understanding concatenation, assignment, and iteration is key to working with arrays
effectively.

#!/bin/bash
br=() # empty array
fruits=("red apple" "golden banana")
fruits+=("navel orange") # append element
echo ${fruits[0]} # "red apple"
echo ${#fruits[*]} #3

fruits[2]="green pear" # reassign element


fruits[6]="seedless watermelon" # gap in index allowed!
echo ${fruits[*]} # all elements

br+=("${fruits[*]}") # copy to another array


echo ${br[*]}

Sparse arrays: Bash allows gaps in array indices — you can assign to index 6 without having assigned indices 3, 4, or 5. This differs from arrays in
languages like C or Java.
Iterating Over Arrays
To process each element in an array, use a for loop with the @ index, wrapped in double quotes to handle elements that contain spaces.

for el in "${br[@]}"
do
echo $el
done

Process
Declare Array For-in Loop
Element

The double-quoted "${array[@]}" syntax ensures that each element is treated as a separate word — even if individual elements contain spaces (like "red apple").
CHAPTER 10

Functions
Writing reusable, modular code in Bash
Defining Functions
Functions let you encapsulate a hard-to-enter command or a sequence of commands into a reusable unit. Once defined, a function name works just like a command
— you can call it and pass arguments to it.

Syntax

function fName () {
commandlist;
}

Inside the function body, commands can be shell built-ins, regular Linux commands, or calls to other functions. Each command must be terminated by a semicolon.
Note that aliases do not work inside functions.

Important: Unlike C or Python, Bash function definitions do not include named parameters in the parentheses. The parentheses must remain empty.
Function Arguments
Since function definitions cannot specify parameter names, arguments are passed and accessed using the familiar positional parameters $1, $2, and so on.

function compare() {
local str1="$1"; ## 1st argument
local str2="$2"; ## 2nd argument
if [[ $str1 == $str2 ]]
then echo 0;
elif [[ $str1 != $str2 ]]
then echo 1;
fi
}
compare "apple" "orange"

The local Keyword Calling Convention


Declares variables that are scoped to the function. Without local, variables Call functions by name, followed by arguments separated by spaces:
are global and can clash with variables elsewhere in your script. compare "apple" "orange". No parentheses are used in the call.
Returning Values from Functions
Bash functions don't return values the way functions in C or Python do. Instead, they use echo to output a result, which can be captured using command
substitution.

Method 1: Echo and Capture

function sum() {
local total=0;
for i in $*
do
let total+=$i
done
echo "Total:" $total
}
prime=("1" "2" "3" "4" "5")
sum ${prime[@]}

Method 2: Reference Parameters

function sum() {
local args="$1[@]";
for i in "${!args}"
do
let $2+=$i
done
}
prime=("1" "2" "3" "4" "5")
myTotal=0
sum prime myTotal
echo "myTotal = " $myTotal # Output: myTotal = 15

The second method passes both the array and the total variable by reference, allowing the function to modify the caller's variable directly.
Passing Script Arguments to Functions
If you want a function to receive the same arguments that were passed to the main script on the command line, you must explicitly forward them using "$@".

function myprint() {
for i in $@
do
echo $i
done
}
myprint "$@"

The "$@" at the bottom forwards all script-level arguments into the function call. Inside the function, $@ refers to the function's own positional parameters — which
are now the same as the script's arguments.
Redefining Built-in Commands
A powerful (and potentially dangerous) feature of Bash is that you can define a function whose name matches an existing built-in or system command. When you do,
the function shadows the original command.

function cd () {
builtin cd "$1"
/bin/ls -l
}
cd $1

This custom cd function changes directory and then automatically lists its contents. The original commands remain accessible through special keywords:

builtin command
Forces execution of the built-in version. Example: builtin cd "$1" calls the Forces execution of the external command version, bypassing both functions
real cd. and built-ins.
REVIEW

Putting It All Together


A complete concept map of everything covered
Shell Scripting Concept Overview

This map illustrates how all the core concepts interconnect. Every topic builds on the foundations of variables and command execution, enabling you to write
increasingly sophisticated automation scripts.
Key Takeaways
01 02 03

Always Start with a Shebang Master the Three Variable Types Choose the Right Control Structure
Every script begins with #!/bin/bash — this tells the Understand positional parameters, environment Use if for general logic, case for pattern matching,
system which interpreter to use and ensures variables, and user-defined variables — they form for for lists, and while/until for condition-based
portability. the backbone of every script. iteration.

04 05

Functions Make Scripts Modular Quote Everything Deliberately


Encapsulate reusable logic in functions. Use local for scoping and echo or Know the difference between single quotes (literal), double quotes (expansion),
reference parameters for return values. and command substitution. Quoting prevents most common scripting bugs.
What's Next?
With these fundamentals in place, you are ready to tackle more advanced scripting topics
including:

Reading values from files — processing configuration files, logs, and CSV data line by line
Regular expressions — advanced pattern matching with grep, sed, and awk

Error handling — using set -e, trap commands, and exit codes for robust scripts
Process management — background jobs, signals, and inter-process communication

Practice by writing small scripts that automate your daily tasks. The best way to learn shell
scripting is to use it — start simple and build complexity gradually.

You might also like