23

Im learning shell scripting from an outdated textbook, and it seems to me like it'd be really usefull to have a program that just returns a string of numbers delimited by spaces something like

$ range 10 20
10 11 12 13 14 15 16 17 18 19 20

Then, if youre doing a shell script you can have

for i in `range 10 20`; do some stuff with numbers in that range;done

does such a thing exist, or do I need to write it myself?

6
  • when you say "unix", do you really mean Linux? Or are you really interested in portability to other systems (Solaris, BSD, ...)? May 28, 2013 at 10:51
  • 2
    s/range/seq - replace range with seq in your example. default separator is newline, to have spaces: seq -s " " 10 20
    – n611x007
    May 28, 2013 at 13:27
  • @naxa Whether it's spaces or newlines does not matter in the for loop—or even any general command that splits arguments—unless you've set the IFS differently.
    – slhck
    May 28, 2013 at 13:46
  • 1
    This question should define what "standard unix program" means to OP. May 28, 2013 at 14:46
  • 1
    As @DavidRivers already commented, you should state in the title and the question your focus is on Linux distributions. The answer you accepted suggests a tool which is NOT a standard Unix program. Several Unix are lacking seq as it is not specified by POSIX.
    – jlliagre
    Aug 22, 2013 at 15:32

7 Answers 7

80

seq is part of coreutils.

for i in $( seq 1 2 11 ) ; do echo $i ; done

Output:

1
3
5
7
9
11

If you provide only 2 arguments to seq, the increment is 1:

$ seq 4 9
4
5
6
7
8
9
5
  • 2
    sed also has nice options like -s to set the separator or -w to qualize the width. And you can provide an increment: seq -w -s ", " 0 5 20 results in 00, 05, 10, 15, 20.
    – scai
    May 28, 2013 at 9:43
  • 2
    @scai you meant seq? May 28, 2013 at 10:09
  • @CarlosCampderrós Of course, unfortunately I can't edit my comment any more.
    – scai
    May 28, 2013 at 11:02
  • 3
    seq 10 20 might also be a simple example worth adding ;) May 28, 2013 at 11:07
  • @scai that is awesome, I learnt something new today :) to be honest, I think you should add that as a separate, more detailed answer! May 28, 2013 at 14:14
34

Would Bash suffice?

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

You can do a lot of things with brace expansion. Bash 4 also supports padded ranges, e.g. {01..20}.

Note that Bash is not considered portable, and not a standard Unix utility. Although you can safely assume that it is installed on most modern Linuxes, don't use this in a script that you plan to run on all kinds of Unix-like machines.

6
  • 13
    @Maksim: Although I also prefer this brace expansion, there's also a typical Un*x tool (do very little, but do that well) for that: seq. The usage is as in your example: seq -s " " 10 20. The -s parameter is necessary, because by default the values are separated by \n.
    – mpy
    May 28, 2013 at 7:13
  • Yeah, Bash isn't "standard" depending on how strict you interpret that. I just find it easier to handle and it doesn't require an extra call.
    – slhck
    May 28, 2013 at 7:18
  • 1
    @mpy, note that seq is a GNU utility, and therefore not a "standard unix program" May 28, 2013 at 10:49
  • 5
    @glennjackman According to developer.apple.com/library/Mac/documentation/Darwin/Reference/…... "The seq command first appeared in Plan 9 from Bell Labs. A seq command appeared in NetBSD 3.0, and ported to FreeBSD 9.0. This command was based on the command of the same name in Plan 9 from Bell Labs and the GNU core utilities. The GNU seq command first appeared in the 1.13 shell utilities release." May 28, 2013 at 11:13
  • Also note that you can do for i in {001..010}; ... ; done and it will zero-pad the number to 3 digits. May 28, 2013 at 15:16
9

If you want something strictly portable (i.e. that does not rely on specific bash extensions or commands not specified by POSIX)

awk 'BEGIN {for(i=10;i<=20;i++) printf "%d ",i; print}'
2
  • 1
    Don't you need to add /dev/null or < /dev/null to that? May 28, 2013 at 15:38
  • 1
    @Scott No, this is not necessary. The POSIX standard ( pubs.opengroup.org/onlinepubs/9699919799/utilities/… ) specifies: If the awk program contains no actions and no patterns, but is otherwise a valid awk program, standard input and any file operands shall not be read and awk shall exit with a return status of zero.
    – jlliagre
    May 28, 2013 at 20:40
6

Before 10.7 there was no seq on Mac OS X, but jot, due to the BSD heritage.

jot -- print sequential or random data

...

HISTORY
    The jot utility first appeared in 4.2BSD

Example:

$ jot - 1 3
1
2
3
0
2

Use a for loop

for ((i = 10; i <= 20; ++i)); do
    printf '%d\n' "$i"
done
1

For the sake of completeness here something that will work with some older variants of Unix (as long as they have perl installed). Not really elegant.

for I in $(perl -e 'print join("\n", 1..10)'); do something with $I; done
1

You can use seq, or if you don't have that, you can write it yourself:

#!/bin/bash
[ $# -ge 1 ] || { echo "Usage: seq Number [ Number ]" 1>&2 ; exit 1; }
[ $# -eq 1 ] && { [ $1 -gt 1 ] && ./seq $(($1 - 1)) ; echo $1 ; }
[ $# -eq 2 ] && { [ $(($2 - $1)) -gt 0 ] && ./seq $1 $(($2 - 1)) ; echo $2 ; }

Usage:

$ ./seq 3
1
2
3

Or:

$ ./seq 3 7
3
4
5
6
7

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .