How does one use a variable in a bash for loop? If I just use a standard for loop, it does what I expect
for i in {0..3}
do echo "do some stuff $i"
doneThis works fine. It loops thru 4 times, 0 to 3 inclusive, printing my message and putting the count at the end.
do some stuff 0
do some stuff 1
do some stuff 2
do some stuff 3When I try the same thing with the following for loop, it seems to equal a string, which is not what i want.
length=3
for i in {0..$length}
do echo "do something right $i"
doneoutput:
do something right {0..3}I've tried
for i in {0.."$length"} and for i in {0..${length}} (both output was {0..3})and
for i in {0..'$length'} (output was {0..$length})and they both don't do what I need. Hopefully someone can help me. Thanks in advance for any bash expert's help with for loops.
13 Answers
One way is using eval:
for i in $( eval echo {0..$length} )
do echo "do something right $i"
doneNote what happens when you set length=;ls or length=; rm * (don't try the latter though).
safely, using seq:
for i in $( seq 0 $length )
do echo "do something right $i"
doneor you can use the c-style for loop, which is also safe:
for (( i = 0; i <= $length; i++ ))
do echo "do something right $i"
done 1 In bash, brace expansion is the first step attempted so, at that point, $length will not have been substituted.
The manpage for bash states clearly:
A sequence expression takes the form {x..y[..incr]}, where x and y are either integers or single characters ...
There are a number of possibilities, such as using:
pax> for i in $(seq 0 $length) ; do echo $i ; done
0
1
2
3though that may give you a large command line if length is massive.
Another alternative is to use the C-like syntax:
pax> for (( i = 0; i <= $length; i++ )) ; do echo $i; done
0
1
2
3It's also possible to omit $ sign in double parentheses to refer a variable:
ubuntu@ip-172-31-28-53:~/playground$ length=3;
ubuntu@ip-172-31-28-53:~/playground$ for ((i=0;i<=length;i++));do echo $i;done
0
1
2
3 Brace subtitutions are performed before any other, so you need to use eval or
a third-party tool like seq.
Example for eval:
for i in `eval echo {0..$length}`; do echo $i; doneThis information can actually be found in man bash:
A sequence expression takes the form {x..y[..incr]}, where x and y are either integers or single characters, and incr, an optional increment, is an integer. [...]
Brace expansion is performed before any other expansions, and any characters special to other expansions are preserved in the result. It is strictly textual. Bash does not apply any syntactic interpretation to the context of the expansion or the text between the braces.