Unit 3: Bash Scripting Fundamentals
I. Orientation
Bash, the Bourne Again Shell, is a command interpreter and scripting language developed for the GNU Project (1989). It executes commands interactively in a terminal or reads them from text files called scripts, making it useful for automation, system administration, file processing, and combining command-line utilities.
- Execution model: Bash reads commands, performs expansions and substitutions, executes them, and records an exit status.
- Command order: Statements normally run sequentially from top to bottom unless conditionals, loops, or functions alter the flow.
- Case sensitivity:
name,Name, andNAMEare different identifiers. - Shell syntax: Spaces, quotation marks, semicolons, and line breaks have syntactic meaning.
- Portability: Code written specifically for Bash may use features unavailable in simpler POSIX shells such as
sh. - Core convention: A status of
0means success; a non-zero status indicates failure or another exceptional result.
II. Script Foundations — Creating and Organizing Programs
A. Introduction to Bash scripting
Bash scripting stores shell commands in a file so that a repeatable task can be executed as one program.
- Purpose: Scripts automate operations such as backups, software setup, log analysis, and file renaming.
- Interpreter: The
bashprogram processes Bash syntax and launches external commands such ascp,grep, andfind. - Execution methods:
bash report.shruns the file through Bash without requiring execute permission../report.shuses the script's shebang and requires execute permission.
- Important distinction: Running
./report.shstarts a child shell, whereassource report.shexecutes commands in the current shell.
B. Bash script structure
A Bash script commonly contains a shebang, comments, variable definitions, commands, control structures, and an explicit exit.
- Shebang: The first line selects the interpreter.
#!/usr/bin/env bash- Main body: Commands and statements appear after the shebang in their required execution order.
- Exit statement:
exit 0explicitly reports successful completion. - Readable layout: Indentation is not generally syntactic, but consistently indenting conditional and loop bodies exposes their structure.
- Safety options:
set -utreats unset variables as errors;set -eexits in many, but not all, failure contexts.
C. Hello World
A Hello World script demonstrates the minimum structure needed to produce output.
- Output command:
printfprovides predictable formatting, whileechois convenient for simple text. - Example:
#!/usr/bin/env bash
printf '%s\n' 'Hello, World!'- Format meaning: In
printf '%s\n',%saccepts a string and\nadds a newline. - Execution: After
chmod +x hello.sh, the command./hello.shprintsHello, World!.
D. Comments
Comments document intent and are ignored by Bash during normal execution.
- Single-line syntax: Text following
#is a comment, except when#!forms the opening shebang.
# Remove reports older than seven days.
find reports -type f -mtime +7 -delete- Placement: Comments may occupy a complete line or follow a command, provided
#is not quoted. - Good practice: Explain why a command exists or why an unusual option is needed, rather than merely restating its syntax.
- No native block syntax: Bash has no dedicated multiline comment operator; consecutive
#lines are clearest.
E. Basic script creation
Basic script creation involves writing the file, granting suitable permissions, and executing it through Bash.
- Create and edit: Use an editor such as
nano task.shorvim task.sh. - Add content:
#!/usr/bin/env bash
printf 'Current directory: %s\n' "$PWD"- Validate syntax:
bash -n task.shchecks parsing without executing ordinary commands. - Make executable:
chmod u+x task.shgrants the owner execute permission. - Run safely:
./task.shruns the file from the current directory; the./prevents Bash from searching onlyPATH.
III. Data and Input — Working with Values
A. Variables
Variables associate names with values and are assigned without spaces around =.
- Assignment:
course="IT Fundamentals"stores a string incourse. - Expansion:
$courseor${course}retrieves the value; braces clarify boundaries in expressions such as"${course}_notes". - Quotation:
"$course"preserves spaces and prevents filename expansion. - Command substitution:
today=$(date +%F)stores command output. - Arithmetic:
total=$((price * quantity))evaluates integer arithmetic. - Environment variables:
export MODE="production"makesMODEavailable to child processes.
B. User input
The read builtin collects text from standard input and stores it in one or more variables.
- Prompting:
read -r -p "Name: " namedisplays a prompt and assigns the response toname. - Backslashes:
-rprevents backslashes from being treated as escape characters and is normally recommended. - Silent input:
read -r -s passwordhides typed characters, which is useful for secrets. - Timed input:
read -r -t 10 answerwaits at most ten seconds. - Validation: Input remains text unless the script checks its format or uses it in an arithmetic context.
C. Arguments
Arguments provide values when a script is launched, as in ./copy.sh source.txt backup.txt.
- Positional parameters:
$1is the first argument,$2the second, and${10}the tenth. - Script identity:
$0contains the invoked script name. - Argument count:
$#gives the number of supplied arguments. - All arguments:
"$@"expands to separate quoted arguments and is safer for iteration than$*. - Argument removal:
shiftdiscards$1and moves later arguments down one position. - Required value:
${1:?Usage: copy.sh SOURCE}terminates with a message when$1is absent or empty.
D. Arrays
Bash supports indexed arrays and associative arrays for storing multiple related values.
- Indexed arrays: Numeric subscripts begin at
0.
servers=("web" "database" "cache")
printf '%s\n' "${servers[1]}"- Associative arrays: String keys require
declare -A.
declare -A ports=([http]=80 [https]=443)
printf '%s\n' "${ports[https]}"- Expansion:
"${servers[@]}"expands every element separately, while"${#servers[@]}"returns the element count. - Iteration:
for server in "${servers[@]}"preserves each element exactly.
E. String slicing
Bash parameter expansion can extract a substring without launching an external program.
- Syntax:
${value:offset:length}selectslengthcharacters starting at zero-basedoffset. - Example:
code="BASH2025"
printf '%s\n' "${code:0:4}" # BASH- Omitted length:
${code:4}returns all characters from position4onward. - Negative offset:
${code: -4}selects the final four characters; the space prevents confusion with the:-default-value operator. - Limitation: Slicing is character-oriented under the active locale and does not perform pattern matching.
IV. Decisions and Status — Controlling Execution
A. Conditional expressions (file, string, arithmetic)
Conditional expressions test system state or values and return an exit status used by control structures.
- File expressions:
[[ -f $path ]]tests for a regular file,-dfor a directory,-efor existence, and-rfor readability. - String expressions:
[[ -z $text ]]tests for an empty string, while[[ $role == admin ]]compares values. - Arithmetic expressions:
(( count >= 10 ))succeeds when the integer comparison is true.
- Preferred syntax:
[[ ... ]]is safer and more expressive in Bash than the older[ ... ]command. - Operators: Within
[[ ]], use==for string comparison; within(( )), use operators such as==,<, and>=numerically.
B. Exit status
Every command produces an integer exit status between 0 and 255.
- Success convention:
0represents success, while non-zero values represent failure or a special condition. - Latest status:
$?contains the status of the most recently completed command.
grep -q "ERROR" app.log
status=$?- Explicit return:
exit 2ends a script with status2;return 2leaves a function. - Command chaining:
command1 && command2runs the second command after success, whereascommand1 || command2runs it after failure. - Preservation: Store
$?immediately because any subsequent command replaces it.
C. If-else statements
An if statement executes different command blocks according to a condition's exit status.
- Structure:
if [[ -f $file ]]; then
printf '%s\n' "File found"
elif [[ -d $file ]]; then
printf '%s\n' "Directory found"
else
printf '%s\n' "Path not found"
fi- Condition: Bash executes the first branch whose test returns
0. - Keywords:
thenbegins a branch,elifadds another condition,elseprovides a fallback, andficloses the statement. - Quotation: Variables used in ordinary commands should remain quoted even when
[[ ... ]]provides safer expansion rules.
D. Switch-case statements
A case statement selects a branch by matching one value against shell patterns.
- Structure:
case $command in
start) start_service ;;
stop) stop_service ;;
*) printf '%s\n' "Unknown command" >&2 ;;
esac- Patterns: Alternatives may be combined as
yes|y|Y, and*acts as the default match. - Termination:
;;ends the selected branch, andesaccloses the statement. - Best use:
caseis clearer than repeatediftests when one value has several possible forms.
V. Repetition and Reuse — Structuring Operations
A. Loops (for, while, until)
Loops repeat commands over values or while a condition has a particular status.
- For loop: Iterates over a known list.
for file in *.log; do
printf '%s\n' "$file"
done- While loop: Repeats while its condition succeeds, as in
while (( count < 5 )). - Until loop: Repeats while its condition fails, as in
until [[ -f ready.flag ]].
- Loop body:
dobegins repeated commands anddonecloses them. - Input loop:
while IFS= read -r line; do ...; done < filesafely processes a file line by line. - Termination: A loop must eventually change the state tested by its condition unless continuous execution is intentional.
B. Break and continue statements
break and continue alter the normal progression of a loop.
- Break:
breakimmediately exits the current loop;break 2exits two nested loop levels. - Continue:
continueskips the remaining body and begins the next iteration;continue 2targets the next iteration of an outer loop.
- Concrete use:
[[ $line == STOP ]] && breakends input processing at a sentinel. - Filtering use:
[[ -z $line ]] && continueskips empty lines. - Control clarity: These statements should represent obvious stopping or skipping rules, not replace a well-defined loop condition.
C. Functions
Functions group reusable commands under a name and execute in the current shell environment.
- Definition:
greet() {
local name=$1
printf 'Hello, %s\n' "$name"
}- Invocation:
greet "Asha"calls the function with"Asha"as$1. - Local variables:
local nameprevents the function from unintentionally replacing a global variable. - Result data: Functions can print data for capture with
result=$(function_name). - Status result:
return 0reports success; return values are statuses, not general strings or large integers.
VI. Development and Shell Customization — Efficient, Persistent Workflows
A. Debugging
Debugging combines syntax checks, execution tracing, status inspection, and deliberate diagnostics.
- Syntax check:
bash -n script.shidentifies parsing errors without normal execution. - Trace mode:
bash -x script.shprints expanded commands before running them. - Local tracing:
set -xenables tracing inside a script, andset +xdisables it. - Diagnostics:
printf 'value=%q\n' "$value" >&2exposes special characters and sends output to standard error. - Common defects: Unquoted variables, incorrect spacing around
=, missingfiordone, and overwritten$?frequently cause failures. - Secret protection: Disable tracing before commands containing passwords, tokens, or private keys.
B. Shortcuts
Bash and terminal keyboard shortcuts accelerate command-line editing and history navigation.
- Movement:
Ctrl+Amoves to the line start,Ctrl+Eto the end, andAlt+BorAlt+Fmoves by words. - Editing:
Ctrl+Udeletes to the line start,Ctrl+Kdeletes to the end, andCtrl+Wdeletes the preceding word. - History:
Ctrl+Rsearches command history; the Up and Down arrows move through entries. - Process control:
Ctrl+Csends an interrupt, whileCtrl+Zsuspends the foreground process. - Completion:
Tabcompletes command names and paths or shows possible matches.
C. Custom commands
A custom command is usually an executable script or function made discoverable through the shell's PATH.
- Executable script: A file with a shebang and execute permission can act like a standard command.
- Command directory: Placing
cleanupin$HOME/binallows direct use when that directory is inPATH. - PATH lookup: Bash searches directories from left to right;
command -v cleanupreveals the selected definition. - Naming: Avoid names that unintentionally replace important system commands.
- Arguments: Custom commands should accept positional parameters, validate them, quote expansions, and return meaningful statuses.
D. Persistent changes
Persistent shell changes are stored in startup files so they are loaded in future sessions.
- Interactive configuration: Bash commonly reads
~/.bashrcfor interactive non-login shells. - Login configuration: Login shells may read
~/.bash_profile,~/.bash_login, or~/.profile, depending on which exists. - PATH example:
export PATH="$HOME/bin:$PATH"- Apply immediately:
source ~/.bashrcreloads the file in the current shell. - Scope: User startup files affect one account; system files such as
/etc/profilecan affect multiple users. - Careful editing: A syntax error in a startup file can disrupt every newly opened shell.
E. Aliases
Aliases replace a command word with predefined text and are best suited to short interactive conveniences.
- Definition:
alias ll='ls -alF'creates the commandll. - Inspection:
alias lldisplays one definition;aliaslists all current aliases. - Removal:
unalias llremoves it from the current shell. - Persistence: Put alias definitions in
~/.bashrcand reload that file. - Limitation: Aliases do not accept parameters as structured functions do; use a function or script for argument handling, branching, or substantial logic.
- Bypassing:
command lsor\lsinvokeslswithout applying an alias namedls.
Did this save you a night before the exam?
LPU Notes is free, and it stays free. Ads cover part of the server bill. The rest comes out of a student's own pocket: the domain, the storage, and keeping the site up through the weeks everyone needs it at once.
The payment button didn't load. An ad blocker or a filtered network is the usual reason. to try again.
Nothing here is ever locked, and nothing unlocks. Chip in only if it was worth it. What it pays for →