Producing a sequence of numbers on a Linux or Mac OS X system

If you need to produce a sequence of sequential or random numbers on a Mac OS X or Linux system among the options available to you are the seq or jot commands, or you can use "brace expansion".

Seq

E.g., if you want to generate the numbers from 1 to 15 in increments of 1, you could use the seq command below:
$ seq 1 15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

You can also specify an increment to use when generating numbers between the start and end numbers. The syntax to use for including an increment is seq start_num increment end_number, where start_num is the first number in the sequence, increment is the number to be added to it to generate the next number, and end_number is the last number in the sequence. E.g., for the sequence generated above, I could also have used seq 1 1 15 to produce the same output, since the default increment is 1. If I used an increment of 2 or 3, I would see the following output:

$ seq 1 2 15
1
3
5
7
9
11
13
15
$ seq 1 3 15
1
4
7
10
13

You can see in the instance where the increment is 3, that the last number in the output is a number that is less than the ending number. I.e., the numbers output won't exceed the end number.

If the ending number given as an argument on the command line is less than the starting number and no increment is specified, then the numbers that are output will be in descending order from the ending number to the starting number with each succeeding number one less than the one before it.

$ seq 15 10
15
14
13
12
11
10

If you do specify an increment and the start number is less than the end number, then you need to use a negative number for the increment value.

$ seq 13 1 10
seq: needs negative decrement
$ seq 13 -1 10
13
12
11
10
$ seq 13 -2 10
13
11
$

You can have leading zeros appear in a number, e.g., 01, instead of 1, by specifying a format for the numbers that will be output, just as you do with the printf command. E.g., if you wished to have numbers displayed as two digit numbers with a zero before the number if it would otherwise be only one digit, e.g., 01, 02, 03, instead of 1, 2, 3, then you could use a command similar to the one below.

$ seq -f "%02g" 1 15
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15

The -f indicates you want to specify a format for the output. The percent sign within the double quotes indicates the start of the format string. The zero followed by a two indicates you want a two digit field with a leading zero, if needed to make the number appear as two digits. So, if you needed a sequence of numbers for the days of the month for a month with 31 days where the number always occupies two columns, you could use seq -f "%02g" 1 31.

Likewise, if you wanted leading zeroes for a three digit output field, you could use a command like the one below.

$ seq -f "%03g" 1 15
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
$

If, instead, you wanted to have the numbers appear right-aligned in three columns, but without any leading zeros, you could use a format like the one below.

$ seq -f "%3g" 1 15
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15

As an alternative to specifying the field width for the numbers with a format string, you can use -w to have leading zeros output if needed to keep the field width consistent for all numbers. E.g., if I wanted to produce numbers between 1 and 12 and have a leading zero output when needed to make the field width two whether the number needed two or only one digits, I could enter a command like the one below.

$ seq -w 1 12
01
02
03
04
05
06
07
08
09
10
11
12

If I changed the end number to 101, I wouldn't have to change a format string, the -w would ensure that every number was displayed as 3 digits to make each consistent with the number of digits used to display the largest number in the sequence.

Generic Category (English)120x600
$ seq -w 1 101
001
002
003
004
005
006
007
008
009
010
011
012
013
< text snipped >
090
091
093
094
095
096
097
098
099
100
101

The numbers you use don't have to be integers. They can contain a fractional component.

$ seq -w 0 .05 .1
0.00
0.05
0.10
$ seq 1.0 0.01 1.15
1
1.01
1.02
1.03
1.04
1.05
1.06
1.07
1.08
1.09
1.1
1.11
1.12
1.13
1.14
$ seq -w 1.0 0.01 1.15
1.00
1.01
1.02
1.03
1.04
1.05
1.06
1.07
1.08
1.09
1.10
1.11
1.12
1.13
1.14

For the last two examples above where the starting number was 1.0 and the ending number was 1.15 with an increment of 0.01 used, you might expect that the last number output would be 1.15, but, instead, it is 1.14. The man page for seq states:

The seq utility prints a sequence of numbers, one per line (default), from first (default 1), to near last as possible, in increments of incr (default 1). When first is larger than last the default incr is -1.

All numbers are interpreted as floating point.

I am presuming that occurs due to rounding occurring associated with the internal floating point representation of the numbers.

Brace Expansion

You can also include numbers in braces separated by two periods and use the echo command to produce numbers output on the same line, instead of on separate lines as is the default with the seq command.

$ echo {1..5}
1 2 3 4 5
$ echo {5..1}
5 4 3 2 1

If you wanted the numbers output by the seq command to appear on the same line, rather than separate lines, you could specify the separator with the -s option followed by a space enclosed in single or double quotes.

$ seq -s " " 1 5
1 2 3 4 5 $

You will notice that in the above example with seq that, because there is no newline, i.e., no line break, after the last number output, that the dollar sign for the Bash shell prompt appears on the same line as the numbers output. I could add a -t parameter to specify a newline after the last number output.

     -t string     Use string to terminate sequence of numbers.  The string
                   can contain character escape sequences in backslash nota-
                   tion as defined in ANSI X3.159-1989 (``ANSI C89'').  This
                   option is useful when the default separator does not con-
                   tain a \n.

E.g. to display the numbers from 1 to 5 on the same line, but then have the dollar sign shell prompt appear on the next line, I could use the following command:

$ seq -s " " -t "\n" 1 5
1 2 3 4 5 
$

Enclosing numbers within braces, separated by two periods works to produce a sequence through "brace expansion" in the Bash shell. From the "Brace Expansion" section of the Bash man page:

Brace Expansion
Brace expansion is a mechanism by which arbitrary strings may be generated. This mechanism is similar to pathname expansion, but the filenames generated need not exist. Patterns to be brace expanded take the form of an optional preamble, followed by either a series of comma-separated strings or a sequence expression between a pair of braces, followed by an optional postscript. The preamble is prefixed to each string contained within the braces, and the postscript is then appended to each resulting string, expanding left to right.

Brace expansions may be nested. The results of each expanded string are not sorted; left to right order is preserved. For example, a{d,c,b}e expands into `ade ace abe'.

A sequence expression takes the form {x..y}, where x and y are either integers or single characters. When integers are supplied, the expression expands to each number between x and y, inclusive. When characters are supplied, the expression expands to each character lexicographically between x and y, inclusive. Note that both x and y must be of the same type.

Brace expansion can be used to generate a sequence of letters as well as numbers.

$ echo {a..m}
a b c d e f g h i j k l m
$ echo {m..a}
m l k j i h g f e d c b a

You can also use brace expansion with the printf command to format numbers with leading zeros.

$ printf "%02g\n" {1..12}
01
02
03
04
05
06
07
08
09
10
11
12

In the example above, I included a \n, which represents a newline, with the format specification, so that I could get each number on a separate line. If I didn't inlude it, I would see the following output where each number occurs immediately after the preceding one with no intervening spaces.

$ printf "%02g" {1..12}
010203040506070809101112$

You can, of course, include other text with the brace expansion, for instance, if you wish to produce file names with sequential numbers at the end.

oreilly.com - Your tech ebook super store
$ echo test{0..5}.txt
test0.txt test1.txt test2.txt test3.txt test4.txt test5.txt

Or I could use the following to put each one on a separate line:

$ echo test{0..5}.txt\\n
test0.txt
 test1.txt
 test2.txt
 test3.txt
 test4.txt
 test5.txt

$

In the above case, when I appended the newline at the end of the echo command, I needed to use two backslash characters before the "n" to get the results I wanted. The first serves as an escape character for the second one. Otherwise I would see the following output:

$ echo test{0..5}.txt\n
test0.txtn test1.txtn test2.txtn test3.txtn test4.txtn test5.txtn

I could use such a command with the touch command to generate empty files by those names on an OS X or Linux system using command substitution.

$ ls -l *.txt
ls: *.txt: No such file or directory
$ touch $(echo test{0..5}.txt\\n)
$ ls -l *.txt
-rw-r--r--  1 jasmith1  wheel  0 May  6 17:07 test0.txt
-rw-r--r--  1 jasmith1  wheel  0 May  6 17:07 test1.txt
-rw-r--r--  1 jasmith1  wheel  0 May  6 17:07 test2.txt
-rw-r--r--  1 jasmith1  wheel  0 May  6 17:07 test3.txt
-rw-r--r--  1 jasmith1  wheel  0 May  6 17:07 test4.txt
-rw-r--r--  1 jasmith1  wheel  0 May  6 17:07 test5.txt
$

Note: if you don't include the \n for a newline character as in the example above, you will get one file with one long name as shown below when it is omitted:

$ touch "$(echo test{0..5}.txt)"
$ ls -l *.txt
-rw-r--r--  1 jasmith1  wheel  0 May  6 16:26 test0.txt test1.txt test2.txt test3.txt test4.txt test5.txt
$

I could also put the seq command in a for loop and use it to generate files with sequential numbers appended to the filenames.

$ ls *.tmp
ls: *.tmp: No such file or directory
$ for n in $(seq 1 5)
> do
> touch test${n}.tmp
> done
$ ls *.tmp
test1.tmp	test2.tmp	test3.tmp	test4.tmp	test5.tmp
$

In the above example, I typed the lines for the for loop at the shell prompt, rather than including them in a Bash script, which is why the greater than sign appears at the beginning of several lines as the Bash shell was prompting me for further input to complete the commands for the loop until I entered "done" to complete the for loop. To use the loop in a Bash script, I could put the following code in the script:

for n in $(seq 1 5)
do
  touch test${n}.tmp
done

If I wanted leading zeros for the numbers, I could just add the -w option.

$ for n in $(seq -w 6 10)
> do
>    touch test${n}.tmp
> done
$ ls *.tmp
test06.tmp	test08.tmp	test1.tmp	test2.tmp	test4.tmp
test07.tmp	test09.tmp	test10.tmp	test3.tmp	test5.tmp

Incidentally, if you wish to generate random numbers, instead of sequential numbers, to use in file names, you can use $RANDOM, which will return a random integer at each invocation. The nominal range is from 0 to 32,767 (signed 16-bit integer). E.g.

Aiseesoft Mac Video Converter Ultimate
$ echo $RANDOM
6619
$ echo $RANDOM
16164
$ echo $RANDOM
26083
$

You can also use a for loop without seq or any other commands but echo to output a list of numbers. E.g., the following loop will output the numbers from zero to one less than ten, i.e., 0 to 9:

$ for (( i=0; i<10; i++ )) ; do echo $i ; done
0
1
2
3
4
5
6
7
8
9

Another alternative is to use a while loop.

counter=0
while [ $counter -lt 10 ]
do
   echo $counter
   counter=`expr $counter + 1`
done

Jot

Or, for either sequential or random numbers, you can use the jot command. If you want to output the natural numbers, aka positive integers, from 1 to some number x, you can use jot x.

$ jot 5
1
2
3
4
5

You can have jot start at any number and output n numbers by specifying jot values start_number. E.g., to have jot display 5 numbers starting at 24, you could use jot 5 12.

$ jot 5 12
12
13
14
15
16

I could also start with a floating point number rather than an integer and have jot add one each time for five iterations. Jot will count using floating point numbers if a decimal point is included on the number.

$ jot 5 24.0
24.0
25.0
26.0
27.0
28.0
$ jot 5 24.2
24.2
25.2
26.2
27.2
28.2

As with the seq command, I can specify a separator character with the -s option. E.g., I could have the numbers appear on the same line with a space between them using -s " ".

$ jot 5
1
2
3
4
5
$ jot -s " " 5
1 2 3 4 5

You can use the -r option to generate a random number. To generate one random number from 1 to 100, you can use jot -r 1. If you wanted five random numbers, you could use jot -r 5. If you aren't specifying the ending number, 100 will be used.

$ jot -r 1
3
$ jot -r 1
17
$ jot -r 1
30
$ jot -r 5
18
50
82
44
4

You can specify the number of values to be produced and the starting and ending numbers as shown below:

$ jot -r 1 25 30
27
$ jot -r 5 25 30
26
30
28
27
28
$ jot -r 10 25 30
26
25
30
27
27
29
29
25
27
25
$

The first example generates one random number between 25 and 30, inclusive of the start and end numbers. The second example above generates 5 such numbers, and the third example generates 10 of them.

You can use the -b option to repeat a string a specific number of times:

$ jot -b hello! 3
hello!
hello!
hello!
$

References:

  1. [Chapter 45] 45.11 The Multipurpose jot Command
    O'Reilly Unix Power Tools

 

TechRabbit ad 300x250 newegg.com

Justdeals Daily Electronics Deals1x1 px