keepcalculator

06 Numbers and Powers

Bash For Loop: How to Use It

Card No. 06·49700 · Updated · Standard formula, shown below

This guide shows you how to use for loops in Bash to repeat commands over a list of items, numbers, files, or command output. You’ll learn the syntax, common patterns, and practical examples you can run in your terminal right away. No prior scripting experience is needed beyond basic command-line navigation.

What You’ll Need

  • A Linux, macOS, or Windows system with Bash installed (Windows users can use Git Bash, WSL, or Cygwin).
  • Access to a terminal or command prompt.
  • Basic familiarity with running commands like echo, ls, and cd.

Step-by-Step

  1. Understand the basic syntax. A Bash for loop looks like this:
    for variable in list; do
        commands
     done

    The variable takes each item from list one by one, and the commands run each time. The semicolons and do/done keywords are required.

  2. Loop over a simple list of words. Type this in your terminal:
    for fruit in apple banana cherry; do
        echo "I like $fruit"
     done

    Press Enter. You’ll see three lines, each with a different fruit. The $fruit expands to the current item.

  3. Loop over a range of numbers. Use curly braces {start..end}:
    for i in {1..5}; do
        echo "Number $i"
     done

    This prints 1 through 5. You can also use a step value: {1..10..2} gives 1, 3, 5, 7, 9.

  4. Use the C-style syntax for more complex conditions. If you need a counter with an increment, use:
    for ((i=0; i<5; i++)); do
        echo "Iteration $i"
     done

    This is similar to C/Java loops. The condition i<5 runs the loop until i reaches 5.

  5. Loop over files in a directory. Use a wildcard to match files:
    for file in *.txt; do
        echo "Found $file"
     done

    This prints all .txt files in the current directory. If no files match, the loop still runs once with the literal *.txt — see Common Mistakes.

  6. Loop over command output. Use $(command) to generate the list:
    for user in $(cut -d: -f1 /etc/passwd); do
        echo "User: $user"
     done

    This prints every username from the passwd file. Be careful with spaces in output — see Tips.

  7. Use the break and continue controls. Inside a loop, break stops the loop entirely, and continue skips to the next iteration:
    for i in {1..10}; do
        if [ $i -eq 5 ]; then
            break
        fi
        echo $i
     done

    This prints 1 through 4 and then stops.

  8. Run a loop as a one-liner. You can write a loop on a single line by separating parts with semicolons:
    for i in {1..3}; do echo $i; done

    This is handy for quick terminal commands.

  9. Put loops in a script. Create a file named loop.sh with nano loop.sh, add the loop, then run bash loop.sh or make it executable with chmod +x loop.sh and run ./loop.sh.

Common Mistakes

  • Missing semicolons or do/done. The syntax is strict. If you see syntax error near unexpected token, check that you have semicolons before do and after the list.
  • Using for i in {1..5} without the braces. If you write for i in 1..5, it treats 1..5 as a literal string, not a range.
  • Spaces around the equals sign in C-style loops. for ((i = 0; i < 5; i++)) is okay, but for ((i=0; i<5; i++)) is more common. Do not put spaces between the variable and = in the assignment part.
  • Forgetting to quote variables. If a filename contains spaces, for file in $list breaks. Always quote: for file in "$list" — but note that quoting the whole list makes it one item. Use arrays or find for filenames with spaces.
  • Looping over an empty glob. If no files match *.txt, Bash passes the literal *.txt as the item. Check with shopt -s nullglob to avoid this.
  • Using echo $i without quotes. While it often works, quoting "$i" prevents word splitting and globbing issues.

Tips

  • Use arrays for lists with spaces. Instead of for fruit in apple "red banana", define an array: fruits=("apple" "red banana"), then loop for fruit in "${fruits[@]}".
  • Use seq for dynamic ranges. for i in $(seq 1 2 10) gives 1,3,5,7,9. This is useful when the step or end is a variable.
  • Test with echo first. Before running a destructive loop (like deleting files), replace the actual command with echo to see what would happen.
  • Use set -x to debug. Add set -x at the top of a script to print each command as it runs, then set +x to turn it off.
  • Prefer find for complex file operations. If you need to process files recursively or with conditions, find with -exec is often more robust than a for loop.
  • Use continue to skip specific items. For example, skip hidden files: for file in *; do [[ $file == .* ]] && continue; echo $file; done.

Troubleshooting

  • Syntax error near unexpected token 'done'. Usually a missing do or a missing semicolon before it. Check that you have do after the list and a semicolon before do if on the same line.
  • Loop runs only once. If you use a variable as the list, like for i in $list, and $list is a single string, it loops once. Use an array or eval (not recommended) to iterate over multiple items.
  • Loop doesn't run at all. If the list is empty, the loop body never executes. For ranges, ensure the start is less than or equal to the end. For globs, check that files exist.
  • Files with spaces are split. Use find with -print0 and while IFS= read -r -d '', or set IFS to newline: IFS=$'\n' before the loop.
  • Command substitution output has newlines. By default, $(command) splits on newlines, but if the output has spaces, it splits on spaces too. Use while IFS= read -r line; do ... done < <(command) to preserve lines.
  • Permission denied when running a script. You need to make the script executable: chmod +x script.sh, or run it with bash script.sh.

Frequently Asked Questions

Can I use a variable as the range end?

Yes, but not directly with brace expansion. Use for ((i=1; i<=$end; i++)) or for i in $(seq 1 $end).

How do I loop through lines of a file?

Use while IFS= read -r line; do echo "$line"; done < file.txt. This handles spaces and special characters correctly.

What's the difference between for and while loops?

for loops iterate over a fixed list or range, while while loops run as long as a condition is true. Use while when you don't know how many iterations you need.

Can I nest for loops?

Yes, you can put one loop inside another. Just ensure each has its own do/done pair and use different variable names.

How do I loop over arguments passed to a script?

Use for arg in "$@"; do echo "$arg"; done. The "$@" expands to all arguments, each properly quoted.

Is there a way to loop forever?

Use for ((;;)); do echo "Ctrl+C to stop"; done or while true; do ...; done. Both run indefinitely until you interrupt them.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →