204

The way to iterate over a range in bash is

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

What would be the syntax for iterating over the sequence with a step? Say, I would like to get only even number in the above example.

codeforester
  • 39,467
  • 16
  • 112
  • 140
SilentGhost
  • 307,395
  • 66
  • 306
  • 293

6 Answers6

258

I'd do

for i in `seq 0 2 10`; do echo $i; done

(though of course seq 0 2 10 will produce the same output on its own).

Note that seq allows floating-point numbers (e.g., seq .5 .25 3.5) but bash's brace expansion only allows integers.

Rob Bednark
  • 25,981
  • 23
  • 80
  • 125
chaos
  • 122,029
  • 33
  • 303
  • 309
  • 5
    I'll hazard a guess that the downvote was due to your answer being generic to 'sh', and not specific to 'bash'. The pure Bash approach {begin end step} performs just a little better.The older 'seq' method's handy on older or smaller-memory systems like busybox. I did upvote both your and TheBonsai's answer. :) – Scott Prive Feb 03 '15 at 02:12
  • 11
    Prefer $(...) to backquotes. Backquotes do not nest sanely. – Omnifarious Aug 23 '18 at 17:07
  • seq 1000000 1000010 only does floats, actually - there's no way to make it do integers! Brace expansion works. – hmijail Jun 23 '20 at 23:06
  • How could I save result(output) into a file? – eawedat May 18 '21 at 15:23
151

Bash 4's brace expansion has a step feature:

for {0..10..2}; do
  ..
done

No matter if Bash 2/3 (C-style for loop, see answers above) or Bash 4, I would prefer anything over the 'seq' command.

TheBonsai
  • 15,513
  • 4
  • 22
  • 14
  • 1
    and btw, do you know if bash4 is default on any major OS? – SilentGhost Jun 08 '09 at 18:03
  • 3
    Bash4 still isn't mainstream, no. Why not seq? Well, let's say it with the words of the bot in the IRC channel #bash: "seq(1) is a highly nonstandard external command used to count to 10 in silly Linux howtos." – TheBonsai Jun 08 '09 at 18:11
  • 1
    my understanding is that seq is a part of coreutils. what is non-standard about it? arguments? thanks for your help. – SilentGhost Jun 08 '09 at 18:14
  • 5
    These arguments may or may not count for you: * there are enough systems without GNU coreutils (but Bash installed) * you create an unneeded external process * you rely on the idea that all 'seq' do what your 'seq' does * it's not standardized by the ISO – TheBonsai Jun 08 '09 at 18:28
  • 4
    @becko If the step is stored in the variable `i`, then you can't do `for {0..10..${i}}` .. it fails. – Nehal J Wani May 17 '14 at 08:18
  • Another reason: thats not as easy with seq: ``echo 0{1..9..2}`` – Jonas Schäfer Jun 05 '14 at 08:54
  • Another reason: `seq 1000000 1000010` only can do floats (look at the manpage!). {1000000..1000010} works as expected. – hmijail Jun 23 '20 at 23:04
99

Pure Bash, without an extra process:

for (( COUNTER=0; COUNTER<=10; COUNTER+=2 )); do
    echo $COUNTER
done
SilentGhost
  • 307,395
  • 66
  • 306
  • 293
Fritz G. Mehner
  • 16,550
  • 2
  • 34
  • 41
  • 14
    +1 Because the step can be replaced by a variable too. – Nehal J Wani May 17 '14 at 08:17
  • 1
    I think this is really what most people likely want -- a simple way to do a loop with a prescribed step value. It sounds simpler than all of the seq based answers, and is a clearer syntax than Bash4 brace expansion, and looks like it would allow for variables (I haven't tried that, but the syntax definitely suggests that). – tobylaroni Mar 05 '19 at 15:02
  • Works in Bash 3, unlike @TheBonsai's answer. – srcerer Oct 30 '19 at 19:03
  • It even resolves variable, ((i="$first" ; i<="$last" ; i+="$step")). Not so easy with curly braces and seq. – Blaa_Thor Dec 04 '19 at 15:15
  • This is sometimes much faster than `{0..10..2}`-style, e.g. when the range is really large. – Ruslan Sep 21 '20 at 21:01
25
#!/bin/bash
for i in $(seq 1 2 10)
do
   echo "skip by 2 value $i"
done
z -
  • 7,130
  • 3
  • 40
  • 68
13

Use seq command:

$ seq 4
1
2
3
4

$ seq 2 5
2
3
4
5

$ seq 4 2 12
4
6
8
10
12

$ seq -w 4 2 12
04
06
08
10
12

$ seq -s, 4
1,2,3,4
Mir-Ismaili
  • 13,974
  • 8
  • 82
  • 100
2

brace expansion {m..n..s} is more efficient than seq. AND it allows a bit of output formatting:

$ echo {0000..0010..2}
0000 0002 0004 0006 0008 0010

which is useful if one numbers e.g. files and want's a sorted output of 'ls'.