How to use variables in a bash for loop

88,607

Solution 1

One way is using eval:

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

Note 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"
done

or 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

Solution 2

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
3

though 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
3

It'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

Solution 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; done

This 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.

Share:
88,607

Related videos on Youtube

Classified
Author by

Classified

Updated on January 02, 2022

Comments

  • Classified
    Classified over 2 years

    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"
    done
    

    This 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 3
    

    When 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"
    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 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.

    • asgs
      asgs over 2 years
      zsh is best suited for that :-)
  • 4xy
    4xy almost 4 years
    It's possible to omit $ sign in double parentheses to refer a variable