Shell Script Tutorial for Beginners - Bash Variables, If, and Loops
Shell scripting is a powerful tool for automating tasks in Linux systems. In this basics edition, you'll learn Bash script syntax from variables and conditionals to loops, with practical examples throughout.
What You'll Learn
- How to create and run your first Bash script with the shebang line and execute permission
- How to define variables, use special variables, and accept user input with
read - How to write
if/elif/elseconditionals andcasestatements with correct syntax - How
for,while, anduntilloops work, including file processing and loop control - The six most common beginner mistakes and how to avoid them
Your First Shell Script
Conclusion: #!/bin/bash, chmod +x, ./script.sh — three steps that start every Bash script.
Basic Structure
#!/bin/bash # This is a comment echo "Hello, Shell Script!" echo "Current date/time: $(date)" echo "Username: $USER"
Creating and Running Scripts
Step 1: Create File
$ nano hello.sh
Enter the above code and save.
Step 2: Add Execute Permission
$ chmod +x hello.sh
Step 3: Run Script
$ ./hello.sh
Hello, Shell Script! Current date/time: Mon Jan 11 14:30:00 JST 2025 Username: user
About Shebang
#!/bin/bash is called a shebang and specifies the interpreter to execute this file.
#!/bin/bash— Use Bash#!/bin/sh— Use POSIX shell#!/usr/bin/env bash— Auto-detect from environment
Variables and Input
Conclusion: No spaces around =; quote all uses; use $() for substitution; read -p for input.
Variable Basics
#!/bin/bash
# Define variables (no spaces around =)
name="Linux User"
age=25
today=$(date +%Y-%m-%d)
# Use variables
echo "Name: $name"
echo "Age: ${age} years old"
echo "Today's date: $today"Calculation Example
#!/bin/bash num1=10 num2=3 sum=$((num1 + num2)) diff=$((num1 - num2)) product=$((num1 * num2)) quotient=$((num1 / num2)) echo "Addition: $num1 + $num2 = $sum" echo "Subtraction: $num1 - $num2 = $diff" echo "Multiplication: $num1 × $num2 = $product" echo "Division: $num1 ÷ $num2 = $quotient"
Special Variables
| Variable | Description | Example |
|---|---|---|
$0 |
Script name | ./script.sh |
$1, $2, ... |
Command line arguments | 1st arg, 2nd arg |
$# |
Number of arguments | 3 for 3 arguments |
$@ |
All arguments | "arg1" "arg2" "arg3" |
$? |
Exit status of last command | 0 for success, non-0 for failure |
$$ |
Current process ID | 12345 |
$USER |
Current username | user |
$HOME |
Home directory | /home/user |
$PWD |
Current directory | /home/user/scripts |
User Input
Basic Input
#!/bin/bash
echo "Please enter your name:"
read name
echo "Hello, ${name}!"Input with Prompt
#!/bin/bash read -p "Enter your age: " age read -s -p "Enter password: " password echo echo "Age: $age" echo "Password entered silently"
Multiple Values at Once
#!/bin/bash echo "Enter name and age (space-separated):" read name age echo "Name: $name, Age: $age"
Conditionals
Conclusion: Spaces inside [ ] required; quote string variables; use -eq/-gt/-lt for numbers.
if Statement
Basic if Statement
#!/bin/bash
read -p "Enter a number: " num
if [ "$num" -gt 0 ]; then
echo "$num is positive"
elif [ "$num" -lt 0 ]; then
echo "$num is negative"
else
echo "$num is zero"
fiFile Existence Check
#!/bin/bash
filename="test.txt"
if [ -f "$filename" ]; then
echo "$filename exists"
echo "File size: $(wc -c < "$filename") bytes"
else
echo "$filename does not exist"
echo "Creating file..."
touch "$filename"
fiConditional Operators
Numeric Comparison
| Operator | Meaning | Example |
|---|---|---|
-eq |
Equal | [ $a -eq $b ] |
-ne |
Not equal | [ $a -ne $b ] |
-gt |
Greater than | [ $a -gt $b ] |
-ge |
Greater or equal | [ $a -ge $b ] |
-lt |
Less than | [ $a -lt $b ] |
-le |
Less or equal | [ $a -le $b ] |
String Comparison
| Operator | Meaning | Example |
|---|---|---|
= |
Equal | [ "$a" = "$b" ] |
!= |
Not equal | [ "$a" != "$b" ] |
-z |
Empty string | [ -z "$str" ] |
-n |
Not empty | [ -n "$str" ] |
File Tests
| Operator | Meaning | Example |
|---|---|---|
-f |
Regular file | [ -f file.txt ] |
-d |
Directory | [ -d /home ] |
-e |
Exists | [ -e path ] |
-r |
Readable | [ -r file ] |
-w |
Writable | [ -w file ] |
-x |
Executable | [ -x script ] |
case Statement
#!/bin/bash
echo "Select an option:"
echo "1) List files"
echo "2) Show current time"
echo "3) Show system info"
echo "4) Exit"
read -p "Choice (1-4): " choice
case $choice in
1)
echo "=== File List ==="
ls -la
;;
2)
echo "=== Current Time ==="
date
;;
3)
echo "=== System Info ==="
uname -a
;;
4)
echo "Exiting."
exit 0
;;
*)
echo "Invalid choice."
;;
esacLoops
Conclusion: {1..N} for ranges, while IFS= read for file lines, until for inverse conditions.
for Loop
Basic for Loop
#!/bin/bash
# Numeric range
for i in {1..5}
do
echo "Count: $i"
done
echo "---"
# File processing
for file in *.txt
do
echo "Processing: $file"
wc -l "$file"
doneLoop with Arrays
#!/bin/bash
fruits=("apple" "banana" "orange" "grape")
echo "Fruit list:"
for fruit in "${fruits[@]}"
do
echo "- $fruit"
doneC-style for Loop
#!/bin/bash
echo "Multiplication table (partial):"
for ((i=1; i<=5; i++))
do
for ((j=1; j<=5; j++))
do
result=$((i * j))
printf "%2d " $result
done
echo
donewhile Loop
Basic while Loop
#!/bin/bash
count=1
while [ $count -le 5 ]
do
echo "Loop iteration $count"
count=$((count + 1))
doneReading Files
#!/bin/bash
filename="data.txt"
if [ -f "$filename" ]; then
while IFS= read -r line
do
echo "Read: $line"
done < "$filename"
else
echo "File $filename not found"
fiuntil Loop
#!/bin/bash
count=1
until [ $count -gt 5 ]
do
echo "Count: $count"
count=$((count + 1))
doneLoop Control
- break — Exit loop
- continue — Skip to next iteration
#!/bin/bash
for i in {1..10}
do
if [ $i -eq 3 ]; then
echo "Skipping 3"
continue
fi
if [ $i -eq 8 ]; then
echo "Stopping at 8"
break
fi
echo "Number: $i"
doneCommon Beginner Mistakes and Pitfalls
Conclusion: Six traps in Bash scripts: spacing, braces, brackets, quotes, backticks, math.
Mistake 1: Spaces in Variable Assignment
NG (causes error)
name = "Taro" # Space before/after = age= 25 # Space after = city ="Tokyo" # Space before =
Results in "command not found" error.
OK (correct usage)
name="Taro" # No spaces around = age=25 city="Tokyo"
Variable assignment must have no spaces around =.
Mistake 2: Missing Braces in Variable Reference
NG (unexpected results)
filename="test" echo "$filenameback.txt" # Empty echo "$filename_backup" # Empty
OK (correct usage)
filename="test"
echo "${filename}back.txt" # testback.txt
echo "${filename}_backup" # test_backupUse {} to clearly define variable name scope.
Mistake 3: Missing Spaces in if Statement Conditions
NG (syntax error)
if [$num -gt 5]; then # No space after [ if [ $num -gt 5]; then # No space before ]
OK (correct usage)
if [ $num -gt 5 ]; then # Spaces inside [ ] required if [[ $num -gt 5 ]]; then # Same for [[ ]] if (( num > 5 )); then # Arithmetic expression
Mistake 4: Missing Quotes in String Comparison
NG (dangerous examples)
if [ $name = John Doe ]; then # Issues with spaces if [ $empty_var = "" ]; then # Error when empty
OK (safe usage)
if [ "$name" = "John Doe" ]; then # Quote both sides if [ "$empty_var" = "" ]; then # No error when empty if [ -z "$var" ]; then # Dedicated empty check option
Mistake 5: Old Command Substitution Syntax
NG (not recommended)
date=`date` # Backticks result=`cat `which ls`` # Nesting causes error
OK (modern syntax)
date=$(date) # Use $() result=$(cat $(which ls)) # Easy to nest
Mistake 6: Arithmetic Operation Errors
NG (not calculated)
result = $num1 + $num2 # Interpreted as a "result" command (command not found) sum="$a + $b" # Not calculated
OK (correct calculation methods)
result=$((num1 + num2)) # Arithmetic expansion let "result = num1 + num2" # Use let command
Basic Rules to Prevent Mistakes
Writing Basics
- Variable assignment: no spaces around
= - Variable usage: always quote
"$var" - Complex variables: use braces
"${var}"
Conditional Basics
- Using
[ ]: always include internal spaces - String comparison: quote both sides
- Numeric comparison: use
-eq,-gt,-lt, etc.
Debugging and Troubleshooting
#!/bin/bash
# Enable debug mode
set -x # Display command execution
set -e # Stop on error
set -u # Error on undefined variables
# Check variable contents
echo "DEBUG: var = [$var]"
# Check file existence
if [ ! -f "$filename" ]; then
echo "ERROR: File $filename not found" >&2
exit 1
fiCommon Error Messages and Solutions
- "command not found": Unnecessary spaces in variable assignment, missing execute permission →
chmod +x script.sh - "syntax error": Missing spaces inside
[ ]in if statement, quote mismatch, missing keywords (then,fi,done) - "Permission denied": No execute permission →
chmod +x script.sh