How to Skip Loop Iteration in Bash
Quick Answer: Skip to the Next Loop Iteration
Use the continue statement to skip the rest of the current iteration and jump immediately to the next one. It keeps the loop running but skips any code after the continue statement in that iteration—essential for filtering out unwanted items.
Quick Comparison: Loop Control Statements
| Method | Effect | Use Case | When to Use |
|---|---|---|---|
| continue | Skip to next iteration | Filter out invalid items | Most common—skip one iteration |
| continue N | Skip N loop levels | Nested loop filtering | Multi-level iteration control |
| break | Exit loop completely | Stop processing entirely | When you’re done, not filtering |
| return | Exit function | Stop everything in function | When conditions require full exit |
Bottom line: Use continue for filtering (skip iteration), break for stopping completely, and combine them to handle complex loop logic.
Skip iterations using the continue statement. The continue command allows you to jump to the next iteration of a loop, skipping remaining commands in the current iteration. This is essential for filtering and conditional processing.
Method 1: Basic Continue in For Loops
Use continue to skip to the next iteration when a condition is met. The loop keeps running but jumps over the remaining code in that iteration.
When to Use Basic Continue
- Skip items matching a pattern or condition
- Exclude unwanted values from processing
- Filter data during iteration without breaking loop
- Process only items passing validation
# Skip specific iteration
for i in {1..5}; do
if [ $i -eq 3 ]; then
continue # Skip iteration when i=3
fi
echo "$i"
done
# Output:
# 1
# 2
# 4
# 5
Example with practical filtering:
# Process only valid items
for item in apple banana cherry; do
if [ "$item" = "banana" ]; then
continue # Skip banana
fi
echo "Fruit: $item"
done
# Output:
# Fruit: apple
# Fruit: cherry
Method 2: Continue in While Loops
While loops benefit from continue when processing conditional data streams or reading files line-by-line with multiple filtering conditions.
When to Use Continue in While Loops
- Skip empty or invalid lines in file processing
- Filter configuration files (skip comments, blanks)
- Process data streams with selective conditions
- Reading user input with validation
count=0
while [ $count -lt 5 ]; do
((count++))
if [ $((count % 2)) -eq 0 ]; then
continue # Skip even numbers
fi
echo "Odd: $count"
done
# Output:
# Odd: 1
# Odd: 3
# Odd: 5
More complex example:
# Process with filtering
while IFS= read -r line; do
# Skip empty lines
[ -z "$line" ] && continue
# Skip lines that start with #
[[ "$line" =~ ^# ]] && continue
# Process valid line
echo "Valid: $line"
done < config.txt
Method 3: Skip Empty Lines and Comments
One of the most practical uses of continue—cleaning data as you process it. Skip empty lines, comments, and invalid entries to process only valid data.
When to Use for Filtering
- Processing configuration files with comments
- Reading user-generated data with formatting issues
- Filtering log files to skip noise
- Validating CSV files during import
# Read file, skip empty lines
while IFS= read -r line; do
[ -z "$line" ] && continue # Skip empty line
echo "Line: $line"
done < input.txt
# Or using grep to show only non-empty:
grep -v '^$' input.txt | while read -r line; do
echo "Line: $line"
done
Method 4: Multi-Condition Filtering
Combine multiple continue statements to skip multiple types of invalid data in a single loop.
# Skip comment lines
while IFS= read -r line; do
[[ "$line" =~ ^#.* ]] && continue # Skip lines starting with #
[ -z "$line" ] && continue # Skip empty lines
echo "Processing: $line"
done < config.txt
Example with real config:
# Input (settings.conf):
# Database Configuration
DB_HOST=localhost
# DB_PORT is obsolete
DB_NAME=mydb
# Processing with continue:
while IFS='=' read -r key value; do
[[ "$key" =~ ^# ]] && continue # Skip comments
[ -z "$key" ] && continue # Skip empty lines
echo "Config: $key = $value"
done < settings.conf
# Output:
# Config: DB_HOST = localhost
# Config: DB_NAME = mydb
Method 5: Continue in Nested Loops
When in nested loops, continue only affects the innermost loop by default. Use continue N to skip multiple nesting levels.
for i in {1..3}; do
echo "Outer: $i"
for j in {1..3}; do
if [ $j -eq 2 ]; then
continue # Continue INNER loop only
fi
echo " Inner: $j"
done
done
# Output:
# Outer: 1
# Inner: 1
# Inner: 3
# Outer: 2
# Inner: 1
# Inner: 3
# Outer: 3
# Inner: 1
# Inner: 3
Method 6: Continue Multiple Nesting Levels
Use continue N to skip to the next iteration of the Nth outer loop, bypassing inner loop iterations entirely.
# Continue outer loop (skip remaining inner iterations)
for i in {1..3}; do
for j in {1..3}; do
if [ $j -eq 2 ]; then
continue 2 # Skip to next i iteration
fi
echo "i=$i, j=$j"
done
done
# Output:
# i=1, j=1
# i=2, j=1
# i=3, j=1
More complex nested example:
for i in {1..2}; do
for j in {1..2}; do
for k in {1..2}; do
if [ $k -eq 2 ]; then
continue 2 # Skip to next j iteration
fi
echo "i=$i, j=$j, k=$k"
done
done
done
# Only processes k=1 for each j
Practical Examples
Example 1: Process Valid Files Only
#!/bin/bash
directory="${1:-.}"
for file in "$directory"/*; do
[ -f "$file" ] || continue # Skip non-files (directories, etc.)
[ -r "$file" ] || continue # Skip non-readable files
[ -s "$file" ] || continue # Skip empty files
# Now process file
lines=$(wc -l < "$file")
echo "$file: $lines lines"
done
Output:
./script.sh: 42 lines
./data.txt: 100 lines
./notes.md: 25 lines
Example 2: Filter Data During Processing
#!/bin/bash
# Read CSV and skip invalid records
csv_file="$1"
while IFS=',' read -r id name age; do
[ "$id" = "id" ] && continue # Skip header
[ -z "$id" ] && continue # Skip empty lines
[ "$age" -lt 18 ] && continue # Skip minors
[[ "$name" =~ ^[A-Za-z]+ ]] || continue # Skip invalid names
# Process valid record
echo "Adult: $name ($age)"
done < "$csv_file"
Example 3: Skip Lines Matching Pattern
#!/bin/bash
# Process log file, skip certain log levels
log_file="$1"
while IFS= read -r line; do
# Skip debug messages
[[ "$line" =~ \[DEBUG\] ]] && continue
# Skip info messages
[[ "$line" =~ \[INFO\] ]] && continue
# Process warnings and errors
echo "$line"
done < "$log_file"
Example 4: Validate and Process Data
#!/bin/bash
# Read data, validate, and skip invalid entries
while IFS=',' read -r email username; do
# Skip header
[ "$email" = "email" ] && continue
# Validate email format (simple)
[[ "$email" =~ ^[^@]+@[^@]+\.[a-z]+$ ]] || continue
# Validate username length
[ ${#username} -lt 3 ] && continue
[ ${#username} -gt 20 ] && continue
# All validations passed
echo "Valid: $username <$email>"
done < users.csv
Example 5: Skip Until Condition Met
#!/bin/bash
# Skip lines until finding marker
while IFS= read -r line; do
# Skip until we find the marker
if [ "$line" = "START" ]; then
continue # Skip START line itself
fi
# Still skipping
if [ "$start_found" != "true" ]; then
continue
fi
# Now process
echo "Processing: $line"
done < input.txt
Better approach:
#!/bin/bash
# Skip lines until marker (better pattern)
found_marker=false
while IFS= read -r line; do
if [ "$line" = "START" ]; then
found_marker=true
continue
fi
# Skip until marker found
[ "$found_marker" = false ] && continue
# Process after marker
echo "Processing: $line"
done < input.txt
Example 6: Function with Continue
#!/bin/bash
# Function using continue in loop
process_items() {
local -a items=("$@")
for item in "${items[@]}"; do
# Skip empty items
[ -z "$item" ] && continue
# Skip items starting with underscore
[[ "$item" =~ ^_ ]] && continue
# Process item
echo "Processing: $item"
done
}
# Usage
process_items "apple" "_hidden" "banana" "" "cherry"
# Output:
# Processing: apple
# Processing: banana
# Processing: cherry
Example 7: Multi-Level Continue
#!/bin/bash
# Example: Search directory tree, skip certain files
for dir in ./*/; do
[ -d "$dir" ] || continue
for file in "$dir"*; do
# Skip hidden files
[[ "$(basename "$file")" =~ ^\. ]] && continue
# Skip backup files
[[ "$file" =~ \.bak$ ]] && continue
# Skip large files
[ -s "$file" ] && [ $(stat -c%s "$file") -gt 1000000 ] && continue
# Process file
echo "Processing: $file"
done
done
Performance Comparison
Using continue vs other methods:
| Approach | Use Case |
|---|---|
| continue | Skip iteration, process remainder |
| if/else | Execute conditional block |
| grep -v | Filter lines (external tool) |
| sed | Complex filtering |
Best choice: Use continue for filtering within loops.
Difference: continue vs break vs return
| Statement | Effect |
|---|---|
continue | Skip to next iteration |
continue N | Skip N loop levels |
break | Exit loop completely |
return | Exit function |
exit | Exit script |
Important Considerations
Continue Level Must Exist
Specifying continue level must not exceed nesting depth:
for i in {1..3}; do
if [ $i -eq 2 ]; then
continue 3 # Error: only 1 level deep
fi
done
# bash: continue: 3: loop level too high
Performance with Many Continues
Many continues can make code harder to read. Consider alternatives:
# Many continues - hard to follow
for line in lines; do
[ -z "$line" ] && continue
[[ "$line" =~ ^# ]] && continue
[ "$count" -gt 100 ] && continue
echo "Process"
done
# Better: use grep or awk
grep -v '^ *$' | grep -v '^#' | ...
Continue in case Statements
While continue works in loops within case statements, it doesn’t work inside case itself:
#!/bin/bash
for item in list; do
case $item in
skip_me)
continue # Works: continue outer loop
;;
process)
echo "Processing: $item"
;;
esac
done
Quick Reference
Patterns for skipping iterations:
# Skip single iteration
for i in list; do
[ condition ] && continue
done
# Skip in while loop
while read line; do
[ condition ] && continue
done
# Skip empty lines
while read line; do
[ -z "$line" ] && continue
done
# Skip comments
while read line; do
[[ "$line" =~ ^# ]] && continue
done
# Continue nested loop (both levels)
for i in list; do
for j in list; do
[ condition ] && continue 2
done
done
Summary
The continue statement is your filtering tool. Use it early and often when processing data—skip empty lines, skip comments, skip invalid entries. Multiple continue statements at the top of a loop make your intent clear: “process only this data.” For nested loops needing multi-level skipping, use continue 2 or continue 3. Always document why you’re skipping with clear conditions so the next person reading your code understands the filtering logic.
Recommended Pattern
#!/bin/bash
# Pattern for filtering while processing
while IFS= read -r line; do
# Skip empty lines
[ -z "$line" ] && continue
# Skip comments
[[ "$line" =~ ^# ]] && continue
# Now process valid line
process_line "$line"
done < input.txt