Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have the following bash script:

#!/bin/bash

upperlim=10

for i in {0..10}
do
echo $i
done

for i in {0..$upperlim}
do
echo $i
done

The first for loop (without the variable upperlim in the loop control) works fine, but the second for loop (with the variable upperlim in the loop control) does not. Is there any way that I can modify the second for loop so that it works? Thanks for your time.

share|improve this question
2  
hm, even for i in {0..$((upperlim))}; do echo $i; donedoes not work – Bonsi Scott Nov 10 '12 at 20:34
    
and +1 because i find that behaviour interesting – Bonsi Scott Nov 10 '12 at 20:36
    
possible cross site duplicate of: stackoverflow.com/questions/169511/… – Ciro Santilli 巴拿馬文件 六四事件 法轮功 Sep 10 '14 at 13:30
    
An external link that answers this: cyberciti.biz/faq/… – kon psych Jun 25 '15 at 5:35
up vote 30 down vote accepted

The reason for this is the order in which things occur in bash. Brace expansion occurs before variables are expanded. In order to accomplish your goal, you need to use C-style for loop:

upperlim=10

for ((i=0; i<=upperlim; i++)); do
   echo "$i"
done
share|improve this answer
1  
And works for zsh as well (but not for csh, tcsh). – math Jan 4 '13 at 17:48

To complete this in your style using nothing but built-ins you'd have to use eval:

d=12

for i in `eval echo {0..$d}`
do
echo $i
done

But with seq:

lowerlimit=0
upperlimit=12

for i in $(seq $lowerlimit $upperlimit)
do
echo $i
done

Personally I find the use of seq to be more readable.

share|improve this answer
    
For "built-ins"? seq is an external command and is not available everywhere bash is. – jordanm Nov 10 '12 at 20:42
7  
@jordanm: For using all builtins with bash. Then I said "but with seq", acknowledging that it's not a built-in. – Jodie C Nov 10 '12 at 20:43
    
The fact that brace expansion is builtin is not the problem here. read is a builtin for example, but there is no reason to eval it. – jordanm Nov 10 '12 at 20:43
    
Builtins are not problematic at all. I wanted to provide an all-bash solution for the asker. If you want to keep arguing about this, take it to chat; comments aren't good for this sort of thing – Jodie C Nov 10 '12 at 20:49

The POSIX way

If you care about portability, use the example from the POSIX standard:

i=2
END=5
while [ $i -le $END ]; do
    echo $i
    i=$(($i+1))
done

Output:

2
3
4
5

Things which are not POSIX:

share|improve this answer

Your approach will not work since in bash brace-expansion occurs before parameter expansion. You need to expand the variable before.

You can work around with eval:

upperlim=10
eval '
        for i in {0..'"$upperlim"'}
        do
                echo $i
        done
'

With While loop:

upperlim=10
#with while
start=0
while [[ $start -le $upperlim ]]
do
    echo "$start"
    ((start = start + 1))
done

Also you can do it with seq command:

upperlim=10
#seq
for i in $(seq "$upperlim"); do
  echo "$i"
done

If you want to run with for i in {0..$upperlim} you will need to use kornshell. eg:

#!/bin/ksh
upperlim=10

for i in {0..$upperlim}
do
        echo $i
done
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.