bash for

Use the bash "for" loops when dealing with a specific number of iterations or an existing list of values.


If you wish to work with a specific number of iterations, bash provides a "for" similar to the c language "for" statement consisting of a conditional statement and an action block.

The conditinal part of the "for" statement contains three parts, initial_condition, test-condition, and condition_adjustment. Each is separated by a semi-colon and the whole is enclosed in double parenthesis.

Structure :

for (( initial_condition; test-condition; condition_adjustment )
do
  action-cmd
done

or
for (( initial_condition; test-condition; condition_adjustment )
{
  action-cmd
}


Example :

for (( i=1; i < 20; i++ )
{
  echo $i
}

"for ((" initializes the conditional portion of the "for" loop. Note the double left parenthesis.

"initial_condition" specifies one or more statements initializing variables to integer values. These variables are usually used to determine the number of iterations but can also just be used to initialize variables used in the action body. If you wish to initialize more than one variable, use commas between each variable.

for (( i=1,j=7; i<7; i++ ); { echo $1; expr $i \* $j; }

"test-condition" specifies one or more integer arithmetic test conditions which if evaluated as true allows the action block to be invoked. To specify more than one condition, use "&&" (and) or "||" (or) between aritmetic statements. The test condition must be integer based mathematical conditions. See the "Aritmetic Evaluation" section of the bash man page for possible conditions.

for (( i=1, j=1; i < 7 && j < 5; i++ ))
{
  read j
  echo $i $j
}

"condition-adjustment" specifies one or more mathematical adjustments to named variables. These are usually the variables being tested but may be other variables containing integer values.

The for loop must have all three portions of the conditional statement separated by the 2 semi-colons. However, any or all of them may be blanks. If blank, the bash shell will assume a 1 or true condition for the missing section. The following is a loop whose test condition is always true. The user may exit by entering a "y" at the prompt. The loop will count the number of times it ran before the user chose to exit.

counter () {
for (( i=1 ;; i++ ))
{
  echo "Times through $i"
  read -p "quit loop (y/n) : " ans

  if test "$ans" = "y"
  then
    break
  fi
}

echo "Times through $i"
}

Some other things to note about the "for" statement :

  • Once the variable i is declared, it continues to exist outside the loop.

  • When referencing i inside the for's condition block, the variable is referenced without the use of the "$", but in the action body, you must use "$" to access the contents of the variable.

  • The "initial-condition" is invoked and then the "test=condition" is evaluated to determine whether to invoke the action block the 1st time through the "for" statement. Each succeeding iteration of the "for" invokes the "condition-adjustment" and then evaluates the "test-condition" to determine whether to invoke the action block again. It is possible to set up conditions where the action body is never executed.

  • This form of for allows the action-cmds or body of the for to be enclosed in either an openning and closing brace, {}. Or it may be enclosed in the do, done pair similar to the while statement.

  • Although many features of bash are based on the original Bourne shell, this style of "for" is not available in the standard "Bourne" shell.


    The other style of "for" is the list form. This style of "for" is borrowed directly from the original Bourne shell.

    The conditional part of this "for" consists of a variable and a list of values to be assigned to it.

    for var in list-element[s]
    do
      action-cmds
    done
    or
    
    for var in list-element[s]
    {
      action-cmds
    }
    

    "for" - the command

    "var" - a variable that will be assigned the next element in the list each time through the loop. This may be any valid variable name. Notice that there is no $ dereferencer used. The for loop is assigning a value to the variable not examining it.

    "in" - keyword separating the variable from the list

    "list-elements[s]" - a list of values to be assigned to the variable one at a time. The list may be literal. Strings with spaces must be quoted.

    for var in  one "and a two" "and three"
    do
      echo $var
    done
    
    More often the command substitution and the desired command will be placed at this position and allowed to generate the list each time the for is executed.

    rmcore() {
    for fn in `find $HOME -name core 2> /dev/null`
    do
      # show user where found, give a long listing and offer to delete
      echo $fn
      ls -l $fn
      rm -i $fn
    done
    }
    

    "for" also supports some predefined list definitions.

    One of the more common lists you may work with is the current directory. The following uses the non-hidden filenames in the current directory as the list :

    for fn in *
    do
      # filename is a directory, list contents
      if test -d $fn
      then
        ls -l $fn
      fi
    done
    

    Another common list is the list of command line arguments passed into a function or shell program. bash supports several variations of the command line argument list in a for statement.

    The following two styles strip any quotes from the argument list and treats each non-space string as a separate strring. Notice that the list references $* and $@ are unquoted.

    # set some command line arguments at the prompt
    set one "and a two" "and three"
    
    for arg in $*
    do
      echo $arg
    done
    
    for arg in $@
    do
      echo $arg
    done
    

    If you quote the $* reference, quotes on each argument are stripped and all arguments are treated as a single string.

    # set some command line arguments at the prompt
    set one "and a two" "and three"
    
    for arg in "$*"
    do
      echo $arg
    done
    

    On the other hand, if you quote the $@ reference, then quotes on each argument on the command line are honored in the for statement.

    # set some command line arguments at the prompt
    set one "and a two" "and three"
    
    for arg in "$@"
    do
      echo $arg
    done
    

    bash provides an abreviated form of this last example. If for is coded with just the for keyword and a variable, it assumes the for arg in "$@" style is intended.

    # set some command line arguments at the prompt
    set one "and a two" "and three"
    for arg
    do
      echo $arg
    done