25

I frequently write for-loops in bash with the well-known syntax:

for i in {1..10}  [...]

Now, I'm trying to write one where the top is defined by a variable:

TOP=10
for i in {1..$TOP} [...]

I've tried a variety of parens, curly-brackets, evaluations, etc, and typically get back an error "bad substitution".

How can I write my for-loop so that the limit depends on a variable instead of a hard-coded value?

abelenky
  • 63,815
  • 23
  • 109
  • 159
  • possible duplicate of [How do I iterate over a range of numbers in bash?](http://stackoverflow.com/questions/169511/how-do-i-iterate-over-a-range-of-numbers-in-bash) – l0b0 Mar 20 '12 at 09:41

3 Answers3

41

You can use for loop like this to iterate with a variable $TOP:

for ((i=1; i<=$TOP; i++))
do
   echo $i
   # rest of your code
done
anubhava
  • 761,203
  • 64
  • 569
  • 643
9

If you have a gnu system, you can use seq to generate various sequences, including this.

for i in $(seq $TOP); do
    ...
done
Kevin
  • 53,822
  • 15
  • 101
  • 132
  • `seq` is not recommended over brace expansion. The behavior between bsd/gnu isn't quite the same. – Daenyth Mar 19 '12 at 22:34
  • @daenyth good to note for when brace expansion is a viable alternative, but the whole point of this question is that brace expansion doesn't work with variable bounds. – Kevin Mar 19 '12 at 23:58
2

Answer is partly there : see Example 11-12. A C-style for loop.

Here is a summary from there, but be aware the final answer to your question depends on your bash interpreter (/bin/bash --version):

# Standard syntax.
for a in 1 2 3 4 5 6 7 8 9 10

# Using "seq" ...
for a in `seq 10`

# Using brace expansion ...
# Bash, version 3+.
for a in {1..10}

# Using C-like syntax.
LIMIT=10
for ((a=1; a <= LIMIT ; a++))  # Double parentheses, and "LIMIT" with no "$".

# another example
lines=$(cat $file_name | wc -l)
for i in `seq 1 "$lines"`

# An another more advanced example: looping up to the last element count of an array :
for element in $(seq 1 ${#my_array[@]})
hornetbzz
  • 9,188
  • 5
  • 36
  • 53