September 2, 2019 at 10:12 AM by Dr. Drang
The Mac comes with two command-line tools for making sequential lists:
seq. In the past, I’ve tended to use
jot, mainly because that’s the one I learned first. But
seq can do almost everything
jot can, and its argument ordering makes more sense in many situations.
The point of both commands is to generate a list of strings that include sequential numbers.1 At their most basic,
seq each produce a set of lines with numbers that count up from one. Both
produce the same output:
1 2 3 4 5
More interesting results come from adding arguments and options.
jot can take up to four arguments;
seq up to three. Here’s a table of how the arguments are ordered.
|2||count first||first last|
|3||count first last||first step last|
|4||count first last step|
As you can see, additional arguments get added to the end for
jot but are inserted for
seq. As we’ve seen above, for the one-argument case,
jot’s count and
seq’s last are effectively the same, because both commands have default starting points and step sizes of 1.2
For the two-argument case, both commands keep the default step size as 1 but allow you to change the starting point. To generate numbers from 5 through 10, you’d use either
jot 6 5
seq 5 10
To me, the
seq arguments are easier to remember and a more natural expression of what’s intended. It’s easy to make an off-by-one error and try
jot 5 5
which will get you only up to 9.
As far as I’m concerned,
jot with three arguments is worthless. If I know the starting and stopping points, and the step size is still at its default of one, the count parameter is redundant. You can avoid doing the subtraction in your head (and then remembering to add 1 to avoid the off-by-one error) by filling the count slot with a hyphen:
jot - 5 10
This is fine, but
seq 5 10 is simpler.
seq and the four-argument
jot allow you to specify the step size. Again,
jot’s count is redundant and it’s best to put a hyphen in its place to allow the computer to do the arithmetic. To get from 10 to 40 counting by 5s, enter
jot - 10 40 5
10 15 20 25 30 35 40
seq command to get the same result is
seq 10 5 40
This is the one place where I find
seq’s arguments hard to remember. So many programming languages use the order first, last, step that my fingers do that before I can stop them. There’s nothing illogical about the first, step, last ordering, but it’s not what I’m used to.
Just printing out lines with numbers is dull. The real value of
seq comes from applying options (often called switches) that allow us format the numbers and include them in other text. Here are the options for
|omit final newline||
The option I use most often is
jot and the nearly equivalent
seq. In both cases, the string argument is a
printf-style formatting string. So if I wanted to generate a bunch of sequential file names, I could use
jot -w "file%02d.txt" 5
seq -f "file%02.0f.txt" 5
file01.txt file02.txt file03.txt file04.txt file05.txt
Here’s a situation where
jot is a little more sensible. Even though both commands treat the numbers they generate as floating point,
jot recognizes when the numbers have no decimal part and allows you to use the
%d format specifier.
seq forces you to use a floating point specifier, like
%e, which then forces you to explicitly state that the number of digits after the decimal point is 0. If you don’t, you’ll get a mess. For example,
seq -f "file%02f.txt" 5
file1.000000.txt file2.000000.txt file3.000000.txt file4.000000.txt file5.000000.txt
-b option for
jot will repeat the given string as many times as specified. The string isn’t a formatting string and won’t include the numbers generated by
jot -b Hello 4
Hello Hello Hello Hello
which I guess could be useful. You might think you could use the
-w option with a string that doesn’t include a formatting specifier. But if you try that,
jot will add the number to the end anyway.
jot -w Hello 4
Hello1 Hello2 Hello3 Hello4
which is kind of presumptuous of it.
seq is better behaved.
seq -f Hello 4
Hello Hello Hello Hello
just as you’d expect.
By the way, if you want just a list of numbers, but you want them zero-padded to be of the same character length,
seq has you covered:
seq -w 8 12
08 09 10 11 12
You could achieve the same thing with a formatting string, but the
-w option is a little shorter.
We’ve been looking at output where each item in the sequence is on its own line—i.e., separated by newlines—but both commands have an
-s option for specifying another separator. The option works a little differently for the two commands.
jot -s, 5 8
seq -s, 8 12
You see that
seq’s “separator” (that’s what it’s called in the man page) is really a suffix. To get the same output as
jot, you can pipe the output through
sed to delete the last character:
seq -s, 8 12 | sed 's/.$//'
Kind of annoying.
seq has over
jot with regard to separators is that it understands tabs.
seq -s "\t" 8 12 | sed 's/.$//'
will give you the numbers separated by tab characters. But
jot treats the backslashed t literally.
jot -s "\t" 5 8
will give you
One more thing related to
jot treats the separator as an actual separator, the newline that’s added by default to the end of the output isn’t handled by
-s. If you don’t want
jot to add it, including the
-n option will omit it. This is just like the
-n option to
As mentioned above, both commands handle floating point numbers, but they have different defaults.
seq -w 7 .5 9
7.0 7.5 8.0 8.5 9.0
as you would expect. But the similar
jot - 7 9 .5
7 8 8 8 9
which seems bizarre. The trick is that
jot has a default precision of zero decimal places, so it’s rounding to the nearest integer. The default precision can be changed with the
jot -p1 - 7 9 .5
7.0 7.5 8.0 8.5 9.0
which is almost certainly what you wanted.
Finally, I want to talk about one clear advantage that
jot has over
seq: the ability to generate sequences of characters using the
jot -c 5 65
A B C D E
What it’s doing is interpreting each number as an ASCII code and returning its corresponding character. Even better, you can use character arguments:
jot -c - a e
a b c d e
You can get the same effect by using the
%c formatting specifier in the
-w option. I’ve used this feature of
jot to generate apartment addresses when working with a building that uses letters for its units. For example, say I am dealing with a five-story building in which the apartments start on the second floor and are given the letters A through D. I want to quickly generate a list of all the apartment addresses. The command is
for n in `seq 2 5`; do jot -w "Apt. $n%c" - A D; done
and the output is
Apt. 2A Apt. 2B Apt. 2C Apt. 2D Apt. 3A Apt. 3B Apt. 3C Apt. 3D Apt. 4A Apt. 4B Apt. 4C Apt. 4D Apt. 5A Apt. 5B Apt. 5C Apt. 5D
As a practical matter, with only 16 apartments, I probably wouldn’t bother with
jot. It’s faster to just type out the apartment addresses when the number is small. But with larger buildings, a command like this saves a lot of time and insures that I don’t skip or duplicate addresses. As with any automation, accuracy is as important as the time saved.
jotalso has an option for generating random numbers, but I’ve never had any use for that. ↩
That the counts start at 1 instead of 0 is an indication that these commands were written for normal humans, not programmers. ↩
The quotation marks aren’t necessary in either of these cases because the shell won’t process the formatting string before sending it to
seq. But I have a hard time remembering which characters are special to the shell, so I tend to use quotation marks any time I have a string that includes potentially special characters like