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.
Your First Shell 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
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
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
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
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