Bash for loop — complete guide

Learn Bash for loops: iterate over lists, ranges, files, arrays, and command output. Copy-paste examples that handle spaces and globs safely.

Tldr

Use `for item in list; do ... done` to iterate. Quote the variable inside the body. For numeric ranges use `{1..5}` or `seq`. For files use globs directly, not `$(ls)`. For arrays use `"${arr[@]}"`.

Intro

The Bash for loop is the workhorse of shell scripting. The right pattern depends on what you are iterating over: a fixed list, a numeric range, files, or array elements. This guide covers each pattern with safe, copy-paste examples.

Steps

Name

Loop over a fixed list

Text

The classic form assigns each word in the list to the loop variable in turn. Quote the variable in the body to preserve values with spaces.

Name

Loop over a numeric range

Text

Brace expansion generates a sequence of numbers. Use `seq` for dynamic ranges or floating-point steps.

Name

Loop over files safely

Text

Globs expand inside the shell and handle filenames with spaces correctly. Enable nullglob so an empty match produces zero iterations instead of the literal pattern.

Name

Loop over an array

Text

Always quote `"${arr[@]}"` so each element stays a single word, even if it contains spaces.

Name

Loop over command output safely

Text

Avoid `for x in $(cmd)` — it word-splits. Use a while-read loop with NUL-delimited output for arbitrary data, or process substitution with a mapfile for arrays.

Name

Control flow with break and continue

Text

Use `break` to exit the loop early and `continue` to skip to the next iteration.

Faq

Q

Why should I quote the loop variable?

A

An unquoted $item is word-split and glob-expanded. If an item is "my file.txt" or "*.log", the body sees multiple words or matching filenames instead of the original value.

Q

How do I loop with an index?

A

Use `${!arr[@]}` to get the indices: `for i in "${!arr[@]}"; do echo "$i: ${arr[$i]}"; done`.

Q

What is the difference between $@ and a for loop?

A

"$@" is the list of positional parameters; a for loop can iterate over any list. You can combine them: `for arg in "$@"; do ... done`.