Shell script "for" loop syntax

940,891

Solution 1

Brace expansion, {x..y} is performed before other expansions, so you cannot use that for variable length sequences.

Instead, use the seq 2 $max method as user mob stated.

So, for your example it would be:

max=10
for i in `seq 2 $max`
do
    echo "$i"
done

Solution 2

Try the arithmetic-expression version of for:

max=10
for (( i=2; i <= $max; ++i ))
do
    echo "$i"
done

This is available in most versions of bash, and should be Bourne shell (sh) compatible also.

Solution 3

Step the loop manually:

i=0
max=10
while [ $i -lt $max ]
do
    echo "output: $i"
    true $(( i++ ))
done

If you don’t have to be totally POSIX, you can use the arithmetic for loop:

max=10
for (( i=0; i &lt max; i++ )); do echo "output: $i"; done

Or use jot(1) on BSD systems:

for i in $( jot 0 10 ); do echo "output: $i"; done

Solution 4

If the seq command available on your system:

for i in `seq 2 $max`
do
  echo "output: $i"
done

If not, then use poor man's seq with perl:

seq=`perl -e "\$,=' ';print 2..$max"`
for i in $seq
do
  echo "output: $i"
done

Watch those quote marks.

Solution 5

We can iterate loop like as C programming.

#!/bin/bash
for ((i=1; i<=20; i=i+1))
do 
      echo $i
done
Share:
940,891

Related videos on Youtube

eykanal
Author by

eykanal

I'm currently working at Google, helping build AI/ML tools for public sector. I've worn a number of hats in the past, including cybersecurity researcher, computational neuroscientist, healthcare technical manager, financial quant, freelance web developer, and IT consultant. I find writing therapeutic; you can read my musings on my blog. Most articles relate to technical management, with the occasional technical discussion. I also find poi spinning to be a pretty awesome hobby as well. You can learn more about me on my LinkedIn page.

Updated on July 22, 2020

Comments

  • eykanal
    eykanal almost 4 years

    I have gotten the following to work:

    for i in {2..10}
    do
        echo "output: $i"
    done
    

    It produces a bunch of lines of output: 2, output: 3, so on.

    However, trying to run the following:

    max=10
    for i in {2..$max}
    do
        echo "$i"
    done
    

    produces the following:

    output: {2..10}
    

    How can I get the compiler to realize it should treat $max as the other end of the array, and not part of a string?

    • whatsisname
      whatsisname over 14 years
      what system and shell are you using? What kind of goofy system has sh or bash, but doesn't have seq, a coreutil?
    • Rahul Das
      Rahul Das over 14 years
      FreeBSD doesn't.
    • a paid nerd
      a paid nerd over 14 years
      Small style nit: I usually see the do and then keywords on the same line as for and if, respectively. E.g., for i in {2..10}; do
    • Barmar
      Barmar almost 11 years
    • jrm
      jrm about 9 years
      FreeBSD, at least 10, does have /usr/bin/seq.
    • Charles Duffy
      Charles Duffy over 3 years
      @whatsisname, seq is not POSIX-standardized. Even if it exists, it's not guaranteed to have any particular behavior. There's a reason none of the patterns discussed in wooledge.org/~greybot/meta/counting (the relevant entry in the freenode #bash channel's factoid database) depend on it.
  • system PAUSE
    system PAUSE over 14 years
    seq is relatively new. I only found out about it a few months ago. But you can use a 'for' loop!! The disadvantage of a 'while' is that you have to remember to increment the counter somewhere inside the loop, or else loop downwards.
  • Flow
    Flow about 12 years
    true $(( i++ )) doesn't work in all cases, so most portable would be true $((i=i+1)).
  • system PAUSE
    system PAUSE about 12 years
    @Flow: Hm, I just tried it on a couple of systems (Linux and BSD based) with #!/bin/sh and it worked fine. Invoked under bash and specifically under /bin/sh, still worked. Maybe the version of sh matters? Are you on some old Unix?
  • chepner
    chepner over 10 years
    Very few systems have a dedicated sh, instead making it a link to other another shell. Ideally, such a shell invoked as sh would only support those features in the POSIX standard, but by default let some of their extra features through. The C-style for-loop is not a POSIX feature, but may be in sh mode by the actual shell.
  • chepner
    chepner over 10 years
    A security risk, since eval will evaluate anything you set max to. Consider max="2}; echo ha; #", then replace echo ha with something more destructive.
  • logan
    logan over 10 years
    semi colon should not come in "for (( i=0; i < max; i++ ));"
  • Conrad Meyer
    Conrad Meyer about 10 years
    (S)he set max to 10. No risk.
  • miller
    miller almost 8 years
    There is no good reason to use an external command such as seq to count and increment numbers in the for loop, hence it is recommend that you avoid using seq. This command is left for compatibility with old bash. The built-in commands are fast enough. for (( EXP1; EXP2; EXP3 )) ...
  • Wernight
    Wernight over 7 years
    @miller the for (( ... )) syntax isn't POSIX and that means for example that it won't work out of the box on things like Alpine Linux. seq does.
  • Franklin Yu
    Franklin Yu about 5 years
    @Wernight Not just Alpine Linux; #!/bin/sh is Dash in Debian/Ubuntu.