for loop syntax in shell script [duplicate]

As heemayl's answer points out, your construction is a bashism. The standard way of doing what you want would be:

for i in 1 2 3 4 5
do
  echo "Random number $i: $RANDOM"
done

Or, more easily expandably:

for i in $(seq 1 5)
do
  echo "Random number $i: $RANDOM"
done

(See man seq for more detail).


Your original script has a (( i=1; i <= 5; i++ )) construct in for loop which is a bashism and hence is not being understood by dash.

In Ubuntu sh is a symbolic link to dash, so when you are running

sh ./script.sh

you are basically running

dash ./script.sh

As i mentioned earlier dash is not understanding the C-like for loop construct, it is showing the error.

To run the script using bash, you can:

  • Run it as as an argument to bash e.g. bash script.sh (you don't need to make the script executable)

  • Make the script executable and from a bash shell run (from the directory containing the script):

    ./script.sh 
    
  • The most portable way is to use a shebang (#!/bin/bash or preferably #!/usr/bin/env bash) as the first line of your script. In this way you can run the script from any shell by ./script.sh, the script will be interpreted as a bash script and hence will be executed accordingly.


Thought I'd contribute to the discussion a little bit.

It's already been mentioned that the syntax used in your script is a bashism and hence isn't portable, even though this is C-like and is well understood by those familiar with java and C. From asking my own question on unix.stackexchange.com , I've also learned that syntax such as for i in $(seq 1 5) generates a set of numbers first and then iterates , which can be wasteful if you have a very large set.

A better way to simulate C-like behavior, which is portable, is to use while loop, with a variable that can be incremented. For instance,

#!/bin/sh
number=0
while [ "$number" -lt 10 ]
do
        printf "\t%d" "$number"
        number=`expr $number + 1 `
done

This works with bash, dash, zsh, ksh, mksh . . . or basically any shell related to bourne shell. In fact, I've a Unix System V book from like 1995, and I've tested their example for bourne shell and it still works. The behaviour is also that of C-like for loop: you have initial condition, testing condition within while [ . . .], and update condition at the end.

csh and tcsh have syntax closer to C language, but its not portable to other shells, and they're not recommended to be used in scripting.

Addition:

Concerning portability of $RANDOM, according to this page on ubuntu wiki, with dash random number generation should rely on using /dev/urandom