Coder Perfect

In a bash loop, how to use variables [duplicate]

Problem

In a bash for loop, how do you use a variable? It accomplishes what I anticipate if I just use a standard for loop.

for i in {0..3}
do
   echo "do some stuff $i"
done

This works perfectly. It repeats the loop four times, from 0 to 3, writing my message and adding the count at the end.

do some stuff 0
do some stuff 1
do some stuff 2
do some stuff 3

When I use the following for loop to do the same thing, it appears to equal a string, which is not what I want.

length=3
for i in {0..$length}
do
   echo "do something right $i"
done

output:

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 neither of them fulfills my requirements. I’m hoping someone can assist me. Thank you in advance for any assistance with for loops from any bash expert.

Asked by Classified

Solution #1

One method is to use eval:

for i in $( eval echo {0..$length} )
do
       echo "do something right $i"
done

Take note of what occurs when you use length=;ls or length=; rm * (the latter is not recommended).

safely, using seq:

for i in $( seq 0 $length )
do
       echo "do something right $i"
done

Alternatively, you can use the safe c-style for looping:

for (( i = 0; i <= $length; i++ )) 
do 
       echo "do something right $i"
done

Answered by perreal

Solution #2

Brace expansion is the first step attempted in bash, therefore $length will not have been substituted at that point.

The manpage for bash clearly states:

There are a variety of options, including using:

pax> for i in $(seq 0 $length) ; do echo $i ; done
0
1
2
3

However, if the command line is really long, this may result in a very long command line.

Another option is to use a C-style syntax:

pax> for (( i = 0; i <= $length; i++ )) ; do echo $i; done
0
1
2
3

It’s also possible to refer to a variable without the $ sign in double parentheses:

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

Answered by paxdiablo

Solution #3

Because brace substitutions come first, you’ll need to use eval or a third-party tool like seq.

Example for eval:

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

This information can be found in the book Man Bash:

Answered by nemo

Post is based on https://stackoverflow.com/questions/17181787/how-to-use-variables-in-a-bash-for-loop