This is an old revision of the document!

The C-style for-loop

for (( <EXPR1> ; <EXPR2> ; <EXPR3> )); do

# as a special case: without semicolon after ((...))
for (( <EXPR1> ; <EXPR2> ; <EXPR3> )) do

# alternative, historical and undocumented syntax

for (( <EXPR1> ; <EXPR2> ; <EXPR3> )) {

The C-style for-loop is, as the name says, derived from the C-keyword "for", but in Bash, it only allows arithmetic expressions as header contents, not arbitrary commands.

It operates as follows: The arithmetic expression <EXPR1> is evaluated, then <EXPR2> is checked, if it's true, then the loop body is executed. After the first iteration, the <EXPR3> is evaluated, <EXPR2> is checked again, if it's true, the loop body is executed, etc…

  • <EXPR1> is to initialize before the first run
  • <EXPR2> is to check if the loop should be ran
  • <EXPR3> is to change conditions after every loop run

It's very simple. Another equivalent loop using a while-construct with arithmetic expressions compound command would be:

(( <EXPR1> ))
while (( <EXPR2> )); do
  (( <EXPR3> ))

If one of these arithmetic expressions in the for-loop is empty, it behaves as if it would be 1 (TRUE in arithmetic context).

:!: Like all loops (both for-loops, while and until), this loop can be

  • terminated (broken) by the break command, optionally as break N to break N levels of nested loops
  • forced to immediately do the next iteration using the continue command, optionally as continue N analog to break N

Bash knows an alternative syntax for the for loop, enclosing the loop body in {...} instead of do ... done:

for ((x=1; x<=3; x++))
  echo $x
This syntax is not documented and should not be used. I found the parser definitions for it in 1.x code, and in modern 4.x code. My guess is that it's there for compatiblity reasons. This syntax is not specified by POSIX(R).

Return status

The return status is the one of the last command executed from <LIST> or FALSE if any of the arithmetic expressions fail.

Simple counter

A simple counter, the loop iterates 101 times ("0" to "100" are 101 numbers → 101 runs!), and everytime the variable x is set to the current value.

  • it initializes x = 0
  • before every iteration it checks if x ⇐ 100
  • after every iteration it changes x++

for ((x = 0 ; x <= 100 ; x++)); do
  echo "Counter: $x"

Stepping counter

This is the very same counter (compare it to the simple counter example above), but the change that is made is a x = x + 10. That means, it will count from 0 to 100, but with a step of 10.

for ((x = 0 ; x <= 100 ; x = x + 10)); do
  echo "Counter: $x"

Bits analyzer

This is a bit more complex, but really just a little bit.

It loops through the bit-values of a Byte, beginning from 128, ending at 1. If that bit is set in the testbyte, it prints "1", else "0" ⇒ it prints the binary representation of the testbyte value (8 bits).

for (( n = 128 ; n >= 1 ; n = n / 2 )); do
  if (( testbyte & n )); then
    echo -n "1"
    echo -n "0"
echo # final linefeed
Why that one begins at 128 (highest value, on the left) and not 1 (lowest value, on the right)? It's easier to print from left to right…

Martin Kealey, 2013/06/06 04:43

It should be noted that the equivalence with the while-loop is approximate; it differ, in that "continue" in a for-loop will cause the 3rd ("increment") expression to be evaluated.

You could leave a comment if you were logged in.