ā¹ļø Skipped - page is already crawled
| Filter | Status | Condition | Details |
|---|---|---|---|
| HTTP status | PASS | download_http_code = 200 | HTTP 200 |
| Age cutoff | PASS | download_stamp > now() - 6 MONTH | 0 months ago |
| History drop | PASS | isNull(history_drop_reason) | No drop reason |
| Spam/ban | PASS | fh_dont_index != 1 AND ml_spam_score = 0 | ml_spam_score=0 |
| Canonical | PASS | meta_canonical IS NULL OR = '' OR = src_unparsed | Not set |
| Property | Value |
|---|---|
| URL | https://linuxize.com/post/bash-for-loop/ |
| Last Crawled | 2026-04-08 12:26:39 (21 hours ago) |
| First Indexed | 2018-11-09 22:06:14 (7 years ago) |
| HTTP Status Code | 200 |
| Meta Title | Bash For Loop: Syntax and Examples | Linuxize |
| Meta Description | A complete guide to the Bash for loop: standard syntax, C-style loops, arrays, ranges, break and continue, and real-world scripting examples. |
| Meta Canonical | null |
| Boilerpipe Text | Loops are a fundamental concept in programming languages. They allow you to execute a series of commands repeatedly until a specific condition is met.
In scripting languages like Bash, loops are especially useful for automating repetitive tasks, eliminating the need to duplicate code.
There are three basic loop constructs in Bash scripting:
for
loop,
while
loop
, and
until
loop
.
This guide focuses on the
for
loop in Bash, including its syntax variations, nesting, flow-control statements like
break
and
continue
, and practical examples.
The Standard Bash
for
Loop
The
for
loop iterates over a list of items and performs the given set of commands.
The basic Bash
for
loop syntax is:
The
[LIST]
can be a series of strings separated by spaces, a range of numbers, command output, an array, command-line arguments, and so on.
Loop Over Strings
The example below shows a loop that iterates over a list of strings. The loop operates on each item in the list, and the variable
element
stores the item that the loop is currently processing.
Loop Over a Range
You can use the sequence expression to
specify a range
of numbers or characters by defining the start and end point of the range. The sequence expression takes the following form:
Here is an example loop that iterates through all numbers from 0 to 3:
Bash also supports specifying an increment when using ranges:
Here is an example showing how to increment by 5:
Loop Over Array Elements
You can use the
for
loop to iterate over the elements of a
Bash array
.
In the example below, we define an array named
BOOKS
and iterate over each element of the array.
The C-style
for
Loop
Bash also supports a C-style
for
loop syntax:
The
INITIALIZATION
part is executed only once when the loop starts. Then, the
TEST
part is evaluated using
comparison operators
. If it is false, the loop is terminated. If the
TEST
is true, commands inside the body of the
for
loop are executed, and the
STEP
part is updated.
In the following example, the loop starts by initializing
i = 0
and, before each iteration, checks whether
i ⤠10
. If true, it
prints
the current value of
i
and increments
i
by 1 (
i++
). Otherwise, the loop terminates.
The loop iterates 11 times and produces the following output:
Nested Loops
A nested loop is a loop inside another loop. You can nest loops to any depth.
In a nested
for
loop, the inner loop runs a complete cycle of its iterations for every outer loop iteration.
Here is an example that copies three files one by one to three servers:
Controlling Loop Flow:
break
and
continue
The
break
and
continue
statements
are used to control the execution of a
for
loop.
break
ā Terminate the Loop
The
break
statement terminates the current loop and passes control to the statement that follows it. It is generally used to exit the loop when a specific condition is met.
In the following example, the
if
statement
terminates the loop once the current item is equal to
Lithium
:
continue
ā Skip to the Next Iteration
The
continue
statement exits the current iteration and passes control to the next one.
In the following example, when the current item equals
2
, the
continue
statement skips the
echo
and moves to the next iteration:
Real-World Examples
Rename Files with Spaces in the Name
The following example renames all files in the current directory that contain a space, replacing spaces with underscores:
*\ *
matches all filenames that contain a space.
${file// /_}
uses
shell parameter expansion
to replace every space with an underscore.
Change File Extension
The following example
renames all files
ending in
.jpeg
in the current directory, replacing the extension with
.jpg
:
*.jpeg
matches all
.jpeg
files in the current directory.
${file%.jpeg}
strips the
.jpeg
suffix using shell parameter expansion, and
.jpg
is appended to form the new name.
The
--
flag prevents
mv
from misinterpreting filenames that start with a dash as options.
Restart Multiple Docker Containers
Here is an example that restarts a list of containers after deploying new code:
Containers are passed to the loop as a list of strings.
Troubleshooting
Loop splits a filename or string with spaces into multiple items
Without quotes, Bash performs word splitting on spaces. Always quote variables and array expansions: use
"${ARRAY[@]}"
instead of
${ARRAY[@]}
, and
"$file"
instead of
$file
.
Glob pattern in the list expands unexpectedly
When a glob pattern like
*.jpeg
matches no files, Bash passes the literal string
*.jpeg
to the loop variable. Add
shopt -s nullglob
before the loop to make unmatched globs expand to nothing instead.
C-style loop does not behave like expected with
[[ ]]
The C-style loop uses arithmetic evaluation ā comparisons inside
(( ))
use
<
,
>
, and
==
directly. Do not mix
[[ ]]
test syntax inside the loop initializer or condition.
Range with a variable does not expand
Brace expansion happens before variable substitution, so
{1..$N}
does not work. Use a C-style loop or
seq
instead:
for i in $(seq 1 "$N"); do
.
Quick Reference
Syntax
Description
for item in a b c; do ... done
Loop over a list of strings
for i in {1..10}; do ... done
Loop over a numeric range
for i in {0..20..5}; do ... done
Loop over a range with increment
for item in "${ARRAY[@]}"; do ... done
Loop over array elements
for ((i=0; i<10; i++)); do ... done
C-style loop
break
Exit the loop immediately
continue
Skip to the next iteration
FAQ
What is the difference between the standard
for
loop and the C-style
for
loop?
The standard
for
loop iterates over a list of items (strings, array elements, a range). The C-style
for
loop uses arithmetic initialization, condition, and step expressions ā it is better suited for counter-based iteration where you control the start, end, and step explicitly.
How do I loop over lines in a file?
Use a
while
loop with
read
instead:
while IFS= read -r line; do echo "$line"; done < file.txt
. A
for
loop is not suited for line-by-line file reading because it splits on whitespace, not newlines.
Can I use
break
or
continue
in nested loops?
Yes. By default,
break
and
continue
affect only the innermost loop. To exit an outer loop from an inner one, use a numeric argument:
break 2
exits two levels of nesting.
How do I loop over command-line arguments?
Use
for arg in "$@"; do
to iterate over all positional parameters passed to the script.
Conclusion
The Bash
for
loop iterates over a list of items or runs for a defined number of iterations using C-style syntax. Combined with
break
,
continue
, nesting, and parameter expansion, it enables elegant solutions to many automation tasks.
To learn all the ways to run your scripts, see
How to Run a Bash Script
.
If you have any questions, feel free to leave a comment below.
Tags
Linuxize Weekly Newsletter
A quick weekly roundup of new tutorials, news, and tips.
Unsubscribe anytime. We respect your inbox.
About the authors
Dejan Panovski
Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.
View author page
Part 26 of 39 |
| Markdown | [Skip to main content](https://linuxize.com/post/bash-for-loop/#main-content)
[Start Here](https://linuxize.com/start-here/) [Linux Commands](https://linuxize.com/tags/linux-commands/) [Bash](https://linuxize.com/tags/bash/) [Ubuntu](https://linuxize.com/tags/ubuntu/) [Python](https://linuxize.com/tags/python/) [Series](https://linuxize.com/series/) [Cheatsheets](https://linuxize.com/cheatsheet/) [About](https://linuxize.com/about/)
Search `/`
- [Start Here](https://linuxize.com/start-here/)
- [Linux Commands](https://linuxize.com/tags/linux-commands/)
- [Bash](https://linuxize.com/tags/bash/)
- [Ubuntu](https://linuxize.com/tags/ubuntu/)
- [Python](https://linuxize.com/tags/python/)
- [Series](https://linuxize.com/series/)
- [Cheatsheets](https://linuxize.com/cheatsheet/)
- [About](https://linuxize.com/about/)
1. [Home](https://linuxize.com/)
2. / [bash](https://linuxize.com/tags/bash/)
3. / Bash For Loop: Syntax and Examples
# Bash For Loop: Syntax and Examples
By
[Dejan Panovski](https://linuxize.com/authors/dejan-panovski/)
ā¢
Updated on Mar 2, 2026
ā¢
8 min read
Series progress
[Bash Scripting Fundamentals](https://linuxize.com/series/bash-scripting-fundamentals/)
Part 26 of 39
On this page
- [The Standard Bash `for` Loop](https://linuxize.com/post/bash-for-loop/#the-standard-bash-for-loop)
- [Loop Over Strings](https://linuxize.com/post/bash-for-loop/#loop-over-strings)
- [Loop Over a Range](https://linuxize.com/post/bash-for-loop/#loop-over-a-range)
- [Loop Over Array Elements](https://linuxize.com/post/bash-for-loop/#loop-over-array-elements)
- [The C-style `for` Loop](https://linuxize.com/post/bash-for-loop/#the-c-style-for-loop)
- [Nested Loops](https://linuxize.com/post/bash-for-loop/#nested-loops)
- [Controlling Loop Flow: `break` and `continue`](https://linuxize.com/post/bash-for-loop/#controlling-loop-flow-break-and-continue)
- [`break` ā Terminate the Loop](https://linuxize.com/post/bash-for-loop/#break--terminate-the-loop)
- [`continue` ā Skip to the Next Iteration](https://linuxize.com/post/bash-for-loop/#continue--skip-to-the-next-iteration)
- [Real-World Examples](https://linuxize.com/post/bash-for-loop/#real-world-examples)
- [Rename Files with Spaces in the Name](https://linuxize.com/post/bash-for-loop/#rename-files-with-spaces-in-the-name)
- [Change File Extension](https://linuxize.com/post/bash-for-loop/#change-file-extension)
- [Restart Multiple Docker Containers](https://linuxize.com/post/bash-for-loop/#restart-multiple-docker-containers)
- [Troubleshooting](https://linuxize.com/post/bash-for-loop/#troubleshooting)
- [Quick Reference](https://linuxize.com/post/bash-for-loop/#quick-reference)
- [FAQ](https://linuxize.com/post/bash-for-loop/#faq)
- [Conclusion](https://linuxize.com/post/bash-for-loop/#conclusion)
Show full outline
Share

Loops are a fundamental concept in programming languages. They allow you to execute a series of commands repeatedly until a specific condition is met.
In scripting languages like Bash, loops are especially useful for automating repetitive tasks, eliminating the need to duplicate code.
There are three basic loop constructs in Bash scripting: `for` loop, [`while` loop](https://linuxize.com/post/bash-while-loop/) , and [`until` loop](https://linuxize.com/post/bash-until-loop/) .
This guide focuses on the `for` loop in Bash, including its syntax variations, nesting, flow-control statements like `break` and `continue`, and practical examples.
## The Standard Bash `for` Loop [\#](https://linuxize.com/post/bash-for-loop/#the-standard-bash-for-loop)
The `for` loop iterates over a list of items and performs the given set of commands.
The basic Bash `for` loop syntax is:
txt
```
for item in [LIST]
do
[COMMANDS]
done
```
The `[LIST]` can be a series of strings separated by spaces, a range of numbers, command output, an array, command-line arguments, and so on.
### Loop Over Strings [\#](https://linuxize.com/post/bash-for-loop/#loop-over-strings)
The example below shows a loop that iterates over a list of strings. The loop operates on each item in the list, and the variable `element` stores the item that the loop is currently processing.
sh
```
for element in Hydrogen Helium Lithium Beryllium
do
echo "Element: $element"
done
```
output
```
Element: Hydrogen
Element: Helium
Element: Lithium
Element: Beryllium
```
### Loop Over a Range [\#](https://linuxize.com/post/bash-for-loop/#loop-over-a-range)
You can use the sequence expression to [specify a range](https://linuxize.com/post/bash-sequence-expression/) of numbers or characters by defining the start and end point of the range. The sequence expression takes the following form:
txt
```
{START..END}
```
Here is an example loop that iterates through all numbers from 0 to 3:
sh
```
for i in {0..3}
do
echo "Number: $i"
done
```
output
```
Number: 0
Number: 1
Number: 2
Number: 3
```
Bash also supports specifying an increment when using ranges:
txt
```
{START..END..INCREMENT}
```
Here is an example showing how to increment by 5:
sh
```
for i in {0..20..5}
do
echo "Number: $i"
done
```
output
```
Number: 0
Number: 5
Number: 10
Number: 15
Number: 20
```
### Loop Over Array Elements [\#](https://linuxize.com/post/bash-for-loop/#loop-over-array-elements)
You can use the `for` loop to iterate over the elements of a [Bash array](https://linuxize.com/post/bash-arrays/) .
In the example below, we define an array named `BOOKS` and iterate over each element of the array.
sh
```
BOOKS=('In Search of Lost Time' 'Don Quixote' 'Ulysses' 'The Great Gatsby')
for book in "${BOOKS[@]}"; do
echo "Book: $book"
done
```
output
```
Book: In Search of Lost Time
Book: Don Quixote
Book: Ulysses
Book: The Great Gatsby
```
## The C-style `for` Loop [\#](https://linuxize.com/post/bash-for-loop/#the-c-style-for-loop)
Bash also supports a C-style `for` loop syntax:
txt
```
for ((INITIALIZATION; TEST; STEP))
do
[COMMANDS]
done
```
The `INITIALIZATION` part is executed only once when the loop starts. Then, the `TEST` part is evaluated using [comparison operators](https://linuxize.com/post/bash-comparison-operators/) . If it is false, the loop is terminated. If the `TEST` is true, commands inside the body of the `for` loop are executed, and the `STEP` part is updated.
In the following example, the loop starts by initializing `i = 0` and, before each iteration, checks whether `i ⤠10`. If true, it [prints](https://linuxize.com/post/echo-command-in-linux-with-examples/) the current value of `i` and increments `i` by 1 (`i++`). Otherwise, the loop terminates.
sh
```
for ((i = 0 ; i <= 10 ; i++)); do
echo "Counter: $i"
done
```
The loop iterates 11 times and produces the following output:
output
```
Counter: 0
Counter: 1
Counter: 2
...
Counter: 8
Counter: 9
Counter: 10
```
## Nested Loops [\#](https://linuxize.com/post/bash-for-loop/#nested-loops)
A nested loop is a loop inside another loop. You can nest loops to any depth.
In a nested `for` loop, the inner loop runs a complete cycle of its iterations for every outer loop iteration.
Here is an example that copies three files one by one to three servers:
sh
```
for f in file_{1..3}; do
for j in server_{1..3}; do
echo "Copying file $f to server $j"
# command to copy files
done
done
```
output
```
Copying file file_1 to server server_1
Copying file file_1 to server server_2
Copying file file_1 to server server_3
Copying file file_2 to server server_1
Copying file file_2 to server server_2
Copying file file_2 to server server_3
Copying file file_3 to server server_1
Copying file file_3 to server server_2
Copying file file_3 to server server_3
```
## Controlling Loop Flow: `break` and `continue` [\#](https://linuxize.com/post/bash-for-loop/#controlling-loop-flow-break-and-continue)
The [`break` and `continue` statements](https://linuxize.com/post/bash-break-continue/) are used to control the execution of a `for` loop.
### `break` ā Terminate the Loop [\#](https://linuxize.com/post/bash-for-loop/#break--terminate-the-loop)
The `break` statement terminates the current loop and passes control to the statement that follows it. It is generally used to exit the loop when a specific condition is met.
In the following example, the [`if` statement](https://linuxize.com/post/bash-if-else-statement/) terminates the loop once the current item is equal to `Lithium`:
sh
```
for element in Hydrogen Helium Lithium Beryllium; do
if [[ "$element" == 'Lithium' ]]; then
break
fi
echo "Element: $element"
done
echo 'All Done!'
```
output
```
Element: Hydrogen
Element: Helium
All Done!
```
### `continue` ā Skip to the Next Iteration [\#](https://linuxize.com/post/bash-for-loop/#continue--skip-to-the-next-iteration)
The `continue` statement exits the current iteration and passes control to the next one.
In the following example, when the current item equals `2`, the `continue` statement skips the `echo` and moves to the next iteration:
sh
```
for i in {1..5}; do
if [[ "$i" == '2' ]]; then
continue
fi
echo "Number: $i"
done
```
output
```
Number: 1
Number: 3
Number: 4
Number: 5
```
## Real-World Examples [\#](https://linuxize.com/post/bash-for-loop/#real-world-examples)
### Rename Files with Spaces in the Name [\#](https://linuxize.com/post/bash-for-loop/#rename-files-with-spaces-in-the-name)
The following example renames all files in the current directory that contain a space, replacing spaces with underscores:
sh
```
for file in *\ *; do
mv "$file" "${file// /_}"
done
```
- `*\ *` matches all filenames that contain a space.
- `${file// /_}` uses [shell parameter expansion](https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html) to replace every space with an underscore.
### Change File Extension [\#](https://linuxize.com/post/bash-for-loop/#change-file-extension)
The following example [renames all files](https://linuxize.com/post/how-to-rename-files-in-linux/) ending in `.jpeg` in the current directory, replacing the extension with `.jpg`:
sh
```
for file in *.jpeg; do
mv -- "$file" "${file%.jpeg}.jpg"
done
```
- `*.jpeg` matches all `.jpeg` files in the current directory.
- `${file%.jpeg}` strips the `.jpeg` suffix using shell parameter expansion, and `.jpg` is appended to form the new name.
- The `--` flag prevents `mv` from misinterpreting filenames that start with a dash as options.
### Restart Multiple Docker Containers [\#](https://linuxize.com/post/bash-for-loop/#restart-multiple-docker-containers)
Here is an example that restarts a list of containers after deploying new code:
sh
```
for container in web db cache redis; do
docker restart "$container" && echo "Restarted $container"
done
```
Containers are passed to the loop as a list of strings.
## Troubleshooting [\#](https://linuxize.com/post/bash-for-loop/#troubleshooting)
**Loop splits a filename or string with spaces into multiple items** Without quotes, Bash performs word splitting on spaces. Always quote variables and array expansions: use `"${ARRAY[@]}"` instead of `${ARRAY[@]}`, and `"$file"` instead of `$file`.
**Glob pattern in the list expands unexpectedly** When a glob pattern like `*.jpeg` matches no files, Bash passes the literal string `*.jpeg` to the loop variable. Add `shopt -s nullglob` before the loop to make unmatched globs expand to nothing instead.
**C-style loop does not behave like expected with `[[ ]]`** The C-style loop uses arithmetic evaluation ā comparisons inside `(( ))` use `<`, `>`, and `==` directly. Do not mix `[[ ]]` test syntax inside the loop initializer or condition.
**Range with a variable does not expand** Brace expansion happens before variable substitution, so `{1..$N}` does not work. Use a C-style loop or `seq` instead: `for i in $(seq 1 "$N"); do`.
## Quick Reference [\#](https://linuxize.com/post/bash-for-loop/#quick-reference)
| Syntax | Description |
|---|---|
| `for item in a b c; do ... done` | Loop over a list of strings |
| `for i in {1..10}; do ... done` | Loop over a numeric range |
| `for i in {0..20..5}; do ... done` | Loop over a range with increment |
| `for item in "${ARRAY[@]}"; do ... done` | Loop over array elements |
| `for ((i=0; i<10; i++)); do ... done` | C-style loop |
| `break` | Exit the loop immediately |
| `continue` | Skip to the next iteration |
## FAQ [\#](https://linuxize.com/post/bash-for-loop/#faq)
**What is the difference between the standard `for` loop and the C-style `for` loop?** The standard `for` loop iterates over a list of items (strings, array elements, a range). The C-style `for` loop uses arithmetic initialization, condition, and step expressions ā it is better suited for counter-based iteration where you control the start, end, and step explicitly.
**How do I loop over lines in a file?** Use a `while` loop with `read` instead: `while IFS= read -r line; do echo "$line"; done < file.txt`. A `for` loop is not suited for line-by-line file reading because it splits on whitespace, not newlines.
**Can I use `break` or `continue` in nested loops?** Yes. By default, `break` and `continue` affect only the innermost loop. To exit an outer loop from an inner one, use a numeric argument: `break 2` exits two levels of nesting.
**How do I loop over command-line arguments?** Use `for arg in "$@"; do` to iterate over all positional parameters passed to the script.
## Conclusion [\#](https://linuxize.com/post/bash-for-loop/#conclusion)
The Bash `for` loop iterates over a list of items or runs for a defined number of iterations using C-style syntax. Combined with `break`, `continue`, nesting, and parameter expansion, it enables elegant solutions to many automation tasks.
To learn all the ways to run your scripts, see [How to Run a Bash Script](https://linuxize.com/post/run-bash-script/) .
If you have any questions, feel free to leave a comment below.
## Tags
[bash](https://linuxize.com/tags/bash/)
## Linuxize Weekly Newsletter
A quick weekly roundup of new tutorials, news, and tips.
## About the authors

Dejan Panovski
Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.
[View author page](https://linuxize.com/authors/dejan-panovski/)
## [Bash Scripting Fundamentals](https://linuxize.com/series/bash-scripting-fundamentals/)
[View all parts](https://linuxize.com/series/bash-scripting-fundamentals/)
Part 26 of 39
[Previous Ā· Part 25 Bash Range: Sequence Expression Syntax and Examples](https://linuxize.com/post/bash-sequence-expression/)
[Next Ā· Part 27 Bash while Loop: Syntax and Examples](https://linuxize.com/post/bash-while-loop/)
## More Like This
- [How to Parse Command-Line Options in Bash with getopts](https://linuxize.com/post/bash-getopts/)
- [Bash Positional Parameters](https://linuxize.com/post/bash-positional-parameters/)
- [Bash Scripting Fundamentals](https://linuxize.com/series/bash-scripting-fundamentals/)
- [Bash Comparison Operators](https://linuxize.com/post/bash-comparison-operators/)
- [How to Run a Bash Script in Linux](https://linuxize.com/post/run-bash-script/)
## You May Also Like
[Feb 28, 2026 ⢠6 min read How to Create Bash Aliases Learn how to create permanent and temporary bash aliases on Linux. This guide covers alias syntax, persistent aliases in .bashrc, and functions that accept arguments.](https://linuxize.com/post/how-to-create-bash-aliases/)
[Feb 27, 2026 ⢠6 min read Bash while Loop: Syntax and Examples The Bash while loop repeatedly executes a block of commands as long as a condition is true. This guide covers the syntax, infinite loops, reading files line by line, and the break and continue statements.](https://linuxize.com/post/bash-while-loop/)
[Feb 11, 2026 ⢠9 min read How to Parse Command-Line Options in Bash with getopts This guide explains how to parse command-line options in Bash with getopts, including option strings, OPTARG and OPTIND, error handling, and practical script examples.](https://linuxize.com/post/bash-getopts/)
## Comments
Ā© 2026 Linuxize.com \| A Raptive Partner Site
[Write For Us](https://linuxize.com/write-for-us/) [Support Us](https://linuxize.com/donate/) [Privacy Policy](https://linuxize.com/privacy-policy/) [Editorial Policy](https://linuxize.com/editorial-policy/) [Terms](https://linuxize.com/terms-of-service/) [Contact](https://linuxize.com/contact/) |
| Readable Markdown | Loops are a fundamental concept in programming languages. They allow you to execute a series of commands repeatedly until a specific condition is met.
In scripting languages like Bash, loops are especially useful for automating repetitive tasks, eliminating the need to duplicate code.
There are three basic loop constructs in Bash scripting: `for` loop, [`while` loop](https://linuxize.com/post/bash-while-loop/) , and [`until` loop](https://linuxize.com/post/bash-until-loop/) .
This guide focuses on the `for` loop in Bash, including its syntax variations, nesting, flow-control statements like `break` and `continue`, and practical examples.
## The Standard Bash `for` Loop
The `for` loop iterates over a list of items and performs the given set of commands.
The basic Bash `for` loop syntax is:
The `[LIST]` can be a series of strings separated by spaces, a range of numbers, command output, an array, command-line arguments, and so on.
### Loop Over Strings
The example below shows a loop that iterates over a list of strings. The loop operates on each item in the list, and the variable `element` stores the item that the loop is currently processing.
### Loop Over a Range
You can use the sequence expression to [specify a range](https://linuxize.com/post/bash-sequence-expression/) of numbers or characters by defining the start and end point of the range. The sequence expression takes the following form:
Here is an example loop that iterates through all numbers from 0 to 3:
Bash also supports specifying an increment when using ranges:
Here is an example showing how to increment by 5:
### Loop Over Array Elements
You can use the `for` loop to iterate over the elements of a [Bash array](https://linuxize.com/post/bash-arrays/) .
In the example below, we define an array named `BOOKS` and iterate over each element of the array.
## The C-style `for` Loop
Bash also supports a C-style `for` loop syntax:
The `INITIALIZATION` part is executed only once when the loop starts. Then, the `TEST` part is evaluated using [comparison operators](https://linuxize.com/post/bash-comparison-operators/) . If it is false, the loop is terminated. If the `TEST` is true, commands inside the body of the `for` loop are executed, and the `STEP` part is updated.
In the following example, the loop starts by initializing `i = 0` and, before each iteration, checks whether `i ⤠10`. If true, it [prints](https://linuxize.com/post/echo-command-in-linux-with-examples/) the current value of `i` and increments `i` by 1 (`i++`). Otherwise, the loop terminates.
The loop iterates 11 times and produces the following output:
## Nested Loops
A nested loop is a loop inside another loop. You can nest loops to any depth.
In a nested `for` loop, the inner loop runs a complete cycle of its iterations for every outer loop iteration.
Here is an example that copies three files one by one to three servers:
## Controlling Loop Flow: `break` and `continue`
The [`break` and `continue` statements](https://linuxize.com/post/bash-break-continue/) are used to control the execution of a `for` loop.
### `break` ā Terminate the Loop
The `break` statement terminates the current loop and passes control to the statement that follows it. It is generally used to exit the loop when a specific condition is met.
In the following example, the [`if` statement](https://linuxize.com/post/bash-if-else-statement/) terminates the loop once the current item is equal to `Lithium`:
### `continue` ā Skip to the Next Iteration
The `continue` statement exits the current iteration and passes control to the next one.
In the following example, when the current item equals `2`, the `continue` statement skips the `echo` and moves to the next iteration:
## Real-World Examples
### Rename Files with Spaces in the Name
The following example renames all files in the current directory that contain a space, replacing spaces with underscores:
- `*\ *` matches all filenames that contain a space.
- `${file// /_}` uses [shell parameter expansion](https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html) to replace every space with an underscore.
### Change File Extension
The following example [renames all files](https://linuxize.com/post/how-to-rename-files-in-linux/) ending in `.jpeg` in the current directory, replacing the extension with `.jpg`:
- `*.jpeg` matches all `.jpeg` files in the current directory.
- `${file%.jpeg}` strips the `.jpeg` suffix using shell parameter expansion, and `.jpg` is appended to form the new name.
- The `--` flag prevents `mv` from misinterpreting filenames that start with a dash as options.
### Restart Multiple Docker Containers
Here is an example that restarts a list of containers after deploying new code:
Containers are passed to the loop as a list of strings.
## Troubleshooting
**Loop splits a filename or string with spaces into multiple items** Without quotes, Bash performs word splitting on spaces. Always quote variables and array expansions: use `"${ARRAY[@]}"` instead of `${ARRAY[@]}`, and `"$file"` instead of `$file`.
**Glob pattern in the list expands unexpectedly** When a glob pattern like `*.jpeg` matches no files, Bash passes the literal string `*.jpeg` to the loop variable. Add `shopt -s nullglob` before the loop to make unmatched globs expand to nothing instead.
**C-style loop does not behave like expected with `[[ ]]`** The C-style loop uses arithmetic evaluation ā comparisons inside `(( ))` use `<`, `>`, and `==` directly. Do not mix `[[ ]]` test syntax inside the loop initializer or condition.
**Range with a variable does not expand** Brace expansion happens before variable substitution, so `{1..$N}` does not work. Use a C-style loop or `seq` instead: `for i in $(seq 1 "$N"); do`.
## Quick Reference
| Syntax | Description |
|---|---|
| `for item in a b c; do ... done` | Loop over a list of strings |
| `for i in {1..10}; do ... done` | Loop over a numeric range |
| `for i in {0..20..5}; do ... done` | Loop over a range with increment |
| `for item in "${ARRAY[@]}"; do ... done` | Loop over array elements |
| `for ((i=0; i<10; i++)); do ... done` | C-style loop |
| `break` | Exit the loop immediately |
| `continue` | Skip to the next iteration |
## FAQ
**What is the difference between the standard `for` loop and the C-style `for` loop?** The standard `for` loop iterates over a list of items (strings, array elements, a range). The C-style `for` loop uses arithmetic initialization, condition, and step expressions ā it is better suited for counter-based iteration where you control the start, end, and step explicitly.
**How do I loop over lines in a file?** Use a `while` loop with `read` instead: `while IFS= read -r line; do echo "$line"; done < file.txt`. A `for` loop is not suited for line-by-line file reading because it splits on whitespace, not newlines.
**Can I use `break` or `continue` in nested loops?** Yes. By default, `break` and `continue` affect only the innermost loop. To exit an outer loop from an inner one, use a numeric argument: `break 2` exits two levels of nesting.
**How do I loop over command-line arguments?** Use `for arg in "$@"; do` to iterate over all positional parameters passed to the script.
## Conclusion
The Bash `for` loop iterates over a list of items or runs for a defined number of iterations using C-style syntax. Combined with `break`, `continue`, nesting, and parameter expansion, it enables elegant solutions to many automation tasks.
To learn all the ways to run your scripts, see [How to Run a Bash Script](https://linuxize.com/post/run-bash-script/) .
If you have any questions, feel free to leave a comment below.
Tags
Linuxize Weekly Newsletter
A quick weekly roundup of new tutorials, news, and tips.
About the authors

Dejan Panovski
Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.
[View author page](https://linuxize.com/authors/dejan-panovski/)
Part 26 of 39 |
| Shard | 72 (laksa) |
| Root Hash | 253233583582590872 |
| Unparsed URL | com,linuxize!/post/bash-for-loop/ s443 |