Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. Shell Script Dictionary
  3. for

for

Since: for 変数 in リスト POSIX(sh互換)
C言語風 for (( )) Bash(bash拡張)

The for statement in shell scripts repeats the same process for each element in a list or sequence. The basic form is for variable in list, which assigns one element at a time to the variable. In bash, you can also use the C-style for ((i=0; i<n; i++)) form. Combined with command substitution ($(command)), you can use command output directly as a list, and combined with file globs, you can process all files in a directory at once.

Basic Syntax

A for loop starts its block with do and closes it with done. Each value listed after in — whether a literal value, variable, or command substitution result — is assigned to the loop variable one at a time.

KeywordMeaningDescription
forStart of the loopDeclares the loop variable and the list to iterate over.
inList specificationLists the values to iterate over. If omitted, $@ (all arguments) is used.
doStart of the body blockMarks the beginning of the statements to repeat.
doneEnd of the body blockCloses the loop (it is "do" spelled backwards).
breakExit the loopImmediately exits the current for loop.
continueSkip to next iterationSkips the remaining statements and moves on to the next element.
# Basic for...in form
for variable in value1 value2 value3; do
    # variable is assigned value1, then value2, then value3 in order
    process
done

# C-style numeric loop (bash only)
for ((i=0; i<n; i++)); do
    process
done

# Brace expansion to generate a sequence (bash only)
for i in {1..5}; do
    process
done

# Command substitution: use command output as the list
for variable in $(command); do
    process
done

# Glob: iterate over files
for file in /path/to/*.txt; do
    process
done

for...in List Form

You can list values separated by spaces after in, or expand an array. To expand an entire array, write "${array[@]}". Without double quotes, elements containing spaces will be split by word splitting.

SyntaxDescription
for x in a b cLists values directly. The list is space-separated.
for x in "${arr[@]}"Safely expands all array elements. Elements containing spaces are treated as a single item.
for x in "${arr[*]}"Expands the array as a single string joined by the IFS separator. Use [@] in most cases.
for x in {1..10}Expands to an integer sequence from 1 to 10 (bash only).
for x in {0..9..2}Expands from 0 to 9 in steps of 2 (bash only, with step).

C-Style for Form (bash only)

The for ((init; condition; update)) form is a bash-only arithmetic for loop. It is useful when you need to control an index or counter. Because it is not available in sh, use a while loop instead when portability is required.

PartDescription
initExecuted once before the loop starts. Sets the initial value of the counter variable.
conditionEvaluated before each iteration. The loop continues while the result is true (non-zero).
updateExecuted after each iteration. Typically increments or decrements the counter.
# Basic C-style form
for ((i=0; i<5; i++)); do
    echo "i = ${i}"
done

# Decrement (countdown)
for ((i=5; i>0; i--)); do
    echo "Countdown: ${i}"
done

# Increment by 2 each step
for ((i=0; i<=10; i+=2)); do
    echo "Even: ${i}"
done

Combining with Command Substitution

You can use the output of $(command) as the list for a for loop. This lets you iterate directly over the output of commands like seq, ls, find, or cat, enabling flexible processing combined with external commands. However, if filenames contain spaces or newlines, glob expansion is safer.

Common combinationDescription
for i in $(seq 1 10)Generates a numeric list from 1 to 10 using the seq command. Works in sh as well.
for line in $(cat file.txt)Iterates over each line of a file. Note that lines containing spaces will be split.
for f in $(find . -name "*.log")Iterates over find results. Cannot handle paths that contain spaces.
for host in $(cat hosts.txt)Iterates over each line in a host list file. Useful for bulk SSH operations.

Iterating Over a File List

To process files in a directory, glob expansion (e.g., *.txt) is safer than command substitution. Because the shell handles glob expansion, it correctly handles filenames that contain spaces. You can also use the nullglob option (bash) to handle the case where no files match.

SyntaxDescription
for f in /dir/*.txtIterates over .txt files in the specified directory.
for f in ./*Iterates over all files and directories in the current directory.
for f in /dir/**/*.logRecursively iterates including subdirectories (requires bash's globstar option).
shopt -s nullglobWhen no files match the glob, prevents the pattern from being treated as a literal string.

Sample Code

yakuza_for_in.sh
#!/bin/bash
# -----------------------------------------------
#  Demonstrates for...in list form
#  using characters from the Yakuza series
# -----------------------------------------------

# -----------------------------------------------
#  Store character names in an array
# -----------------------------------------------

characters=("桐生一馬" "真島吾朗" "秋山駿" "冴島大河" "錦山彰")

echo "=== Yakuza Character List ==="
echo ""

# Iterate over all array elements with for...in
# Always enclose "${array[@]}" in double quotes
# so that names containing spaces are treated as single elements
for chara in "${characters[@]}"; do
    echo "  - ${chara}"
done

echo ""
echo "=== Display with Numbers ==="
echo ""

# Use C-style for to display with an index
for ((i=0; i<${#characters[@]}; i++)); do
    # ${#array[@]} returns the number of elements in the array
    echo "  ${i}: ${characters[$i]}"
done

echo ""
echo "Character count: ${#characters[@]}"
$ chmod +x yakuza_for_in.sh
$ ./yakuza_for_in.sh
=== Yakuza Character List ===

  - 桐生一馬
  - 真島吾朗
  - 秋山駿
  - 冴島大河
  - 錦山彰

=== Display with Numbers ===

  0: 桐生一馬
  1: 真島吾朗
  2: 秋山駿
  3: 冴島大河
  4: 錦山彰

Character count: 5
yakuza_c_style_for.sh
#!/bin/bash
# -----------------------------------------------
#  Demonstrates C-style for loop
#  using characters from the Yakuza series
# -----------------------------------------------

# -----------------------------------------------
#  Store character combat scores in an array
# -----------------------------------------------

names=("桐生一馬" "真島吾朗" "秋山駿" "冴島大河" "錦山彰")
scores=(9800 9500 8200 9100 8700)

echo "=== Combat Score Ranking (C-style for) ==="
echo ""

# Control the index with C-style for
# Increment i from 0 up to (but not including) the array length
for ((i=0; i<${#names[@]}; i++)); do
    name="${names[$i]}"
    score="${scores[$i]}"
    printf "  #%d  %-16s  Score: %d\n" "$((i + 1))" "${name}" "${score}"
done

echo ""
echo "=== Countdown (Decrement) ==="
echo ""

# Decrement i from the array length down to 1
for ((i=${#names[@]}; i>=1; i--)); do
    echo "  Rank ${i}: ${names[$((i - 1))]}"
done

echo ""
echo "=== Show Only Even-Index Characters ==="
echo ""

# Step by 2 to pick only even-index elements
for ((i=0; i<${#names[@]}; i+=2)); do
    echo "  ${names[$i]} (index ${i})"
done
$ chmod +x yakuza_c_style_for.sh
$ ./yakuza_c_style_for.sh
=== Combat Score Ranking (C-style for) ===

  #1  桐生一馬          Score: 9800
  #2  真島吾朗          Score: 9500
  #3  冴島大河          Score: 9100
  #4  錦山彰            Score: 8700
  #5  秋山駿            Score: 8200

=== Countdown (Decrement) ===

  Rank 5: 錦山彰
  Rank 4: 冴島大河
  Rank 3: 秋山駿
  Rank 2: 真島吾朗
  Rank 1: 桐生一馬

=== Show Only Even-Index Characters ===

  桐生一馬 (index 0)
  秋山駿 (index 2)
  錦山彰 (index 4)
yakuza_cmd_sub_for.sh
#!/bin/bash
# -----------------------------------------------
#  Combines command substitution with a for loop
#  to process character data files
# -----------------------------------------------

# -----------------------------------------------
#  Prepare working directory and data files
# -----------------------------------------------

work_dir="./yakuza_data"
mkdir -p "${work_dir}"

# Create an information file for each character
echo "桐生一馬 神室町 極道" > "${work_dir}/kiryu.txt"
echo "真島吾朗 蒼天堀 狂犬" > "${work_dir}/majima.txt"
echo "秋山駿   横浜 探偵" > "${work_dir}/akiyama.txt"
echo "冴島大河 北海道 熊殺し" > "${work_dir}/saejima.txt"
echo "錦山彰   神室町 龍" > "${work_dir}/nishikiyama.txt"

echo "=== Iteration with seq command ==="
echo ""

# Use seq to generate numbers 1–5 and iterate over them
# The $() command substitution uses seq's output as the list
for i in $(seq 1 5); do
    echo "  Round ${i} start"
done

echo ""
echo "=== Iterate over find results to process files ==="
echo ""

# Search for text files with find and receive the results via command substitution
# Safe to use as long as filenames do not contain spaces
for filepath in $(find "${work_dir}" -name "*.txt" | sort); do
    filename=$(basename "${filepath}" .txt)
    content=$(cat "${filepath}")
    echo "  [${filename}] ${content}"
done

echo ""
echo "=== Safely iterate over files using glob expansion ==="
echo ""

# Glob expansion handles filenames with spaces correctly
# Prefer glob over command substitution for file iteration
for f in "${work_dir}"/*.txt; do
    # Check that the file exists before processing
    if [ -f "${f}" ]; then
        echo "  Processing: $(basename ${f})"
    fi
done

# Remove the working directory to clean up
rm -rf "${work_dir}"
echo ""
echo "Cleanup complete."
$ chmod +x yakuza_cmd_sub_for.sh
$ ./yakuza_cmd_sub_for.sh
=== Iteration with seq command ===

  Round 1 start
  Round 2 start
  Round 3 start
  Round 4 start
  Round 5 start

=== Iterate over find results to process files ===

  [akiyama] 秋山駿   横浜 探偵
  [kiryu] 桐生一馬 神室町 極道
  [majima] 真島吾朗 蒼天堀 狂犬
  [nishikiyama] 錦山彰   神室町 龍
  [saejima] 冴島大河 北海道 熊殺し

=== Safely iterate over files using glob expansion ===

  Processing: akiyama.txt
  Processing: kiryu.txt
  Processing: majima.txt
  Processing: nishikiyama.txt
  Processing: saejima.txt

Cleanup complete.
yakuza_break_continue.sh
#!/bin/bash
# -----------------------------------------------
#  Demonstrates the use of break and continue
# -----------------------------------------------

names=("桐生一馬" "真島吾朗" "秋山駿" "冴島大河" "錦山彰")
# Status flag for each character (1: available, 0: resting)
status=(1 1 0 1 0)

echo "=== continue: Skip characters who are resting ==="
echo ""

for ((i=0; i<${#names[@]}; i++)); do
    # Use continue to skip when status is 0 (resting)
    if [ "${status[$i]}" -eq 0 ]; then
        echo "  ${names[$i]}: Resting — skipped"
        continue
    fi
    echo "  ${names[$i]}: Ready"
done

echo ""
echo "=== break: Stop searching once Kiryu is found ==="
echo ""

target="桐生一馬"
found=0

for chara in "${names[@]}"; do
    echo "  Searching: ${chara}"
    # Use break to exit the loop when the target is found
    if [ "${chara}" = "${target}" ]; then
        echo "  → Found ${target}! Stopping search."
        found=1
        break
    fi
done

echo ""
if [ "${found}" -eq 1 ]; then
    echo "Found: ${target}"
else
    echo "${target} was not found."
fi
$ chmod +x yakuza_break_continue.sh
$ ./yakuza_break_continue.sh
=== continue: Skip characters who are resting ===

  桐生一馬: Ready
  真島吾朗: Ready
  秋山駿: Resting — skipped
  冴島大河: Ready
  錦山彰: Resting — skipped

=== break: Stop searching once Kiryu is found ===

  Searching: 桐生一馬
  → Found 桐生一馬! Stopping search.

Found: 桐生一馬

Summary

Shell script for loops come in two forms: for variable in list, and the bash-only for ((init; condition; update)). When iterating over all elements of an array, enclose the expansion in double quotes as "${array[@]}" to prevent elements containing spaces from being split. Using command substitution ($()), you can iterate directly over the output of commands like seq or find, but this cannot handle filenames with spaces. For file iteration, glob expansion (e.g., *.txt) is the safer choice. Use break to exit a loop immediately, and continue to skip the current iteration and move to the next. When combining loops with conditionals, also refer to the if statement page.

If you find any errors or copyright issues, please .