Sample output
$ seq -w 1 12
01
02
03
04
05
06
07
08
09
10
11
12
Twelve months, each two digits wide, ready to drop into a filename like report-2026-07.csv where a plain 7 would sort after 10 and break every glob that expects a fixed width.
When you would reach for it
Building month or day numbers for dated filenames, looping over numbered hosts like web01 through web12, or generating test fixtures that need to sort correctly with ls. It is also the answer when the upper bound lives in a variable: {1..$n} does not expand in bash because brace expansion runs before variable expansion, but seq -w 1 "$n" does what you meant.
Gotchas
- When the first number is larger than the last, GNU seq on Debian prints nothing and exits 0, because the step still defaults to 1. The BSD seq on macOS counts down on its own. Pass the step explicitly,
seq 12 -1 1, and both platforms agree. - The width comes from the endpoints, so a sequence that stays inside one digit gets no padding.
seq -w 1 9prints1to9. For a fixed width regardless of range, useseq -f '%02g' 1 9, which always pads to two. - seq prints in
%gformat when it cannot tell the numbers are plain integers, and the macOS version does this sooner than GNU.seq 999999 1000001can show1e+06on a Mac. Add-f '%.0f'when a script will handle large numbers on both systems. - Negative numbers count the minus sign toward the width.
seq -w -5 5prints-5through-1, then00,01, and so on, because-5is two characters wide.
Variants
$ seq -f 'web%02g' 1 12
A prefix and fixed-width padding in one format string. Prints web01 through web12. GNU and macOS; BusyBox on Alpine has no -f
$ echo report-2026-{01..12}.csv
Bash 4 and zsh. A leading zero on either bound tells brace expansion to pad every term to the wider bound, with no external program. Literal bounds only, no variables
$ seq -s+ 1 100 | bc
-s swaps the newline for any separator, so seq writes the expression 1+2+...+100 and bc adds it up. Prints 5050