🔢 seq Command

Generate Sequences of Numbers in Linux

About the seq Command

The seq command generates sequences of numbers, printing them to standard output. It's a simple but incredibly useful tool for creating numeric sequences in shell scripts, loops, data generation, and testing. Seq can generate sequences with custom increments, formatting, and separators, making it versatile for various automation tasks.

Why it's useful: While bash has built-in range syntax like {1..10}, seq offers more flexibility with floating-point numbers, custom formatting (padding, decimal places), and dynamic ranges from variables. It's particularly valuable in scripts where you need precise control over number generation or when working with decimal values.

Common applications: Loop counters, generating test data, creating numbered filenames, batch processing, parallel job control, countdown timers, and mathematical sequence generation.

Basic Syntax: seq [OPTIONS] LAST seq [OPTIONS] FIRST LAST seq [OPTIONS] FIRST INCREMENT LAST Common Usage: seq 5 # Generate 1 2 3 4 5 seq 3 7 # Generate 3 4 5 6 7 seq 1 2 10 # Generate 1 3 5 7 9 (increment by 2) seq -w 1 100 # Generate 001 002 ... 100 (equal width) seq -s, 1 5 # Generate 1,2,3,4,5 (comma separator) seq -f "file%03g.txt" 1 5 # Generate file001.txt file002.txt ... Common Options: -f, --format=FORMAT Use printf-style format (default: %g) -s, --separator=STRING Use STRING as separator (default: newline) -w, --equal-width Equalize width by padding with leading zeros

Detailed Examples

1Basic Sequence Generation

Generate simple numeric sequences with different syntaxes.

$ seq 5
1 2 3 4 5
$ seq 3 7
3 4 5 6 7
$ seq 10 15
10 11 12 13 14 15
What's happening: Seq has three forms: (1) seq LAST generates from 1 to LAST. (2) seq FIRST LAST generates from FIRST to LAST. (3) seq FIRST INCREMENT LAST (see example 2). By default, seq prints one number per line, making it perfect for piping to other commands or using in loops. The sequences are inclusive - both FIRST and LAST are included in the output. Default behavior: When you specify only one number, seq starts at 1. When you specify two numbers, seq increments by 1. Each number is printed on its own line, which is ideal for shell processing where each line is treated as a separate item.
The output goes to stdout, so you can redirect it: seq 5 > numbers.txt or pipe it: seq 5 | xargs echo

2Custom Increment (Step)

Generate sequences with custom increments, including negative and decimal values.

$ seq 0 5 20
0 5 10 15 20
$ seq 10 -2 0
10 8 6 4 2 0
$ seq 0 0.5 2.5
0.0 0.5 1.0 1.5 2.0 2.5
What's happening: The three-argument form seq FIRST INCREMENT LAST allows custom step values. First example: Count from 0 to 20 in steps of 5 (multiples of 5). Second example: Countdown from 10 to 0 in steps of -2 (negative increment for decreasing sequences). Third example: Decimal increments work perfectly - count from 0 to 2.5 in steps of 0.5. Important behavior: Seq stops when the next value would exceed LAST (or go below LAST for negative increments). If LAST isn't exactly reachable (e.g., seq 1 2 10 can't hit 10 exactly), seq stops at the last valid value (9 in this case). Floating-point arithmetic is supported, making seq more flexible than bash's brace expansion which only handles integers.
Negative increments create countdown sequences: seq 60 -1 0 for a 60-second countdown timer.
Bash brace expansion {1..10} doesn't support decimals or variables, but seq does: seq 1 0.1 2 works perfectly.

3Custom Separator

Change the output separator from newline to any string.

$ seq -s ' ' 1 5
1 2 3 4 5
$ seq -s ', ' 1 5
1, 2, 3, 4, 5
$ seq -s $'\t' 1 5
1 2 3 4 5
$ seq -s '|' 10 2 20
10|12|14|16|18|20
What's happening: The -s (separator) option changes what appears between numbers. Default is newline, but you can use any string. First example: Space-separated output, all on one line. Second example: Comma-space separator for CSV-style output. Third example: Tab separator using $'\t' (ANSI-C quoting in bash). Fourth example: Pipe separator. Practical uses: Creating CSV data (-s ','), formatting for display (-s ', '), generating arrays for other languages, or creating URLs with dashes. The separator only appears between values, not before the first or after the last value.

Creating CSV Data

$ echo "ID,Value" > data.csv $ for i in $(seq 5); do echo "$i,$(($i * 10))" done >> data.csv
For inline arrays in scripts: array=($(seq -s ' ' 1 10)) creates a bash array.

4Equal Width with Leading Zeros

Pad numbers with leading zeros for consistent width.

$ seq 8 12
8 9 10 11 12
$ seq -w 8 12
08 09 10 11 12
$ seq -w 1 100
001 002 003 ... 098 099 100
What's happening: The -w (equal-width) option pads numbers with leading zeros so all output has the same width. Seq determines the width based on the widest number in the sequence (LAST or FIRST, whichever is wider). First example (no -w): Numbers 8-12 have varying widths (1 or 2 digits). Second example (with -w): All numbers are 2 digits wide, with 8 and 9 padded as 08 and 09. Third example: Generating 001-100, all 3 digits wide. Why this matters: Equal-width numbers sort correctly as strings (important for filenames), create aligned output in tables, and work better with systems that expect fixed-width fields. Without padding, string sorting gives "1, 10, 11, 2, 3..." instead of "1, 2, 3, 10, 11...".

Creating Numbered Filenames

$ for i in $(seq -w 1 100); do touch "file_${i}.txt" done $ ls file_*.txt | head -5
file_001.txt file_002.txt file_003.txt file_004.txt file_005.txt
Equal-width padding is automatic - you don't specify the width, seq calculates it from the range.

5Printf-Style Formatting

Use custom format strings for precise control over output.

$ seq -f "Number: %g" 3 5
Number: 3 Number: 4 Number: 5
$ seq -f "file_%03g.txt" 1 5
file_001.txt file_002.txt file_003.txt file_004.txt file_005.txt
$ seq -f "Item #%02g: %.2f units" 1 3
Item #01: 1.00 units Item #02: 2.00 units Item #03: 3.00 units
$ seq -f "%04g" 1 5
0001 0002 0003 0004 0005
What's happening: The -f (format) option uses printf-style format strings where %g is replaced by each number. Format specifiers: %g = general number format (default). %03g = pad to 3 digits with zeros. %f = floating-point. %.2f = 2 decimal places. %e = scientific notation. First example: Adds prefix text to each number. Second example: Creates filenames with zero-padded numbers (alternative to -w). Third example: Complex formatting with both padding and decimal places. Fourth example: Zero-padding to 4 digits. This is more powerful than -w because you can add text before and after the number, control decimal places, and use other printf features.
The format string can include any text, but must contain exactly one numeric format specifier (%g, %f, %e, etc.). Use %% to include a literal percent sign.

6Using seq in For Loops

Common pattern: using seq to control loop iterations.

#!/bin/bash # Process files in batches for i in $(seq 1 5); do echo "Processing batch $i..." sleep 1 done echo "All batches complete!"
$ ./script.sh Processing batch 1... Processing batch 2... Processing batch 3... Processing batch 4... Processing batch 5... All batches complete!
#!/bin/bash # Countdown timer for i in $(seq 5 -1 1); do echo "$i..." sleep 1 done echo "Blast off!"
$ ./countdown.sh 5... 4... 3... 2... 1... Blast off!
What's happening: Seq is commonly used in for loops to iterate a specific number of times or with specific values. First example: Simple counter from 1 to 5 for batch processing. The $(seq 1 5) expands to "1 2 3 4 5" which the for loop iterates over. Second example: Countdown using negative increment. Each iteration, $i takes the next value from the sequence. Alternative syntax: You could use bash's C-style for loop (for ((i=1; i<=5; i++))) or brace expansion (for i in {1..5}), but seq offers more flexibility with decimals, negative increments, and variable ranges. Important note: When the range comes from variables, you must use seq: for i in $(seq $start $end) works, but {$start..$end} doesn't (brace expansion happens before variable expansion).
For variable ranges, seq is essential: end=10; for i in $(seq 1 $end); do echo $i; done works perfectly.
Modern bash also supports for i in {1..10} brace expansion, but it's less flexible than seq (no decimals, no variables, no custom increments > 1).

7Generating Test Data

Create test files, sample data, or mock records.

#!/bin/bash # Create test log files with timestamps for i in $(seq -w 1 30); do date=$(date -d "$i days ago" "+%Y-%m-%d") echo "[$date] Application started" > "log_${i}.txt" echo "[$date] Processing complete" >> "log_${i}.txt" done echo "Created 30 test log files"
#!/bin/bash # Generate sample CSV data echo "ID,Name,Value" > sample.csv for i in $(seq 1 100); do value=$((RANDOM % 1000)) echo "$i,User$i,$value" >> sample.csv done echo "Generated 100 sample records"
#!/bin/bash # Create numbered directories for organization for year in $(seq 2020 2025); do for month in $(seq -w 1 12); do mkdir -p "archives/${year}/${month}" done done echo "Created directory structure for 2020-2025"
What's happening: Seq is perfect for generating test data at scale. First example: Creates 30 numbered log files with dates going back 30 days. The -w flag ensures log_01.txt through log_30.txt sort correctly. Second example: Generates 100 rows of CSV data with IDs, names, and random values. Seq provides the sequential IDs, while bash's RANDOM provides variety. Third example: Creates a nested directory structure for 6 years × 12 months = 72 directories. Uses nested seq loops with -w for month numbers (01-12). Why this matters: Testing often requires realistic volumes of data. Seq makes it trivial to generate thousands of files, records, or data points with sequential identifiers. Combined with shell scripting, you can create complex test scenarios quickly.
Combine seq with other tools: seq 1 1000 | xargs -I{} curl -s "https://api.example.com/user/{}" fetches data for users 1-1000.

8Parallel Processing with Seq

Distribute work across parallel processes using sequences.

#!/bin/bash # Process files in parallel batches TOTAL_FILES=100 BATCH_SIZE=10 for batch_start in $(seq 1 $BATCH_SIZE $TOTAL_FILES); do batch_end=$((batch_start + BATCH_SIZE - 1)) echo "Processing files $batch_start to $batch_end" # Process batch in background ( for i in $(seq $batch_start $batch_end); do echo " Processing file_${i}.txt" # Simulate work sleep 0.1 done ) & done # Wait for all background jobs wait echo "All batches complete!"
$ ./parallel.sh Processing files 1 to 10 Processing files 11 to 20 Processing files 21 to 30 ... Processing file_1.txt Processing file_11.txt Processing file_21.txt ... All batches complete!
What's happening: This demonstrates using seq for parallel batch processing. The outer loop uses seq 1 10 100 to generate batch starting points: 1, 11, 21, 31... 91. Each batch processes 10 files (1-10, 11-20, etc.) in a subshell backgrounded with &. All batches run simultaneously (parallel processing). The wait command ensures the script doesn't exit until all background jobs complete. Real-world application: This pattern is valuable for CPU-bound tasks where you want to use multiple cores, or I/O-bound tasks where you can parallelize network requests. Advantages: Seq makes it easy to divide work into chunks. Variables let you adjust BATCH_SIZE dynamically. You can scale from 10 to 10,000 files just by changing one number. Alternative tools: GNU parallel or xargs -P can do similar things but with more features. Seq provides the basic building block for DIY parallelism.
Control parallel job count: Use sem (from GNU parallel package) or implement a simple semaphore to limit concurrent processes.

9Mathematical Sequences and Calculations

Generate mathematical sequences and perform calculations.

$ seq 1 2 20
1 3 5 7 9 11 13 15 17 19
$ seq 0 0.1 1 | head -5
0.0 0.1 0.2 0.3 0.4
#!/bin/bash # Calculate sum of numbers 1 to 100 sum=0 for i in $(seq 1 100); do sum=$((sum + i)) done echo "Sum of 1 to 100: $sum"
Sum of 1 to 100: 5050
#!/bin/bash # Generate Fibonacci-like sequence using seq as counter a=0 b=1 for i in $(seq 1 10); do echo $a next=$((a + b)) a=$b b=$next done
0 1 1 2 3 5 8 13 21 34
What's happening: Seq is useful for mathematical operations and sequence generation. First example: Odd numbers (increment by 2 starting at 1). Second example: Decimal sequence from 0 to 1 in steps of 0.1, useful for precision tests or graphing data points. Third example: Sum calculation using seq to provide the numbers and bash arithmetic to accumulate. This reproduces Gauss's famous formula: sum = n(n+1)/2 = 100×101/2 = 5050. Fourth example: Fibonacci sequence where seq just provides iteration count (1-10) while bash arithmetic generates the actual Fibonacci numbers. Applications: Test calculations, generate data points for plotting, create arithmetic or geometric sequences, or provide iteration counts for complex calculations. While seq doesn't do the math itself, it provides the controlled iteration needed for mathematical algorithms.
For pure math, tools like bc, awk, or Python might be better. Seq excels at providing the iteration control and simple sequences.

10Advanced Formatting and Integration

Complex formatting and integration with other commands.

$ seq -f "https://example.com/api/user/%g" 1 5
https://example.com/api/user/1 https://example.com/api/user/2 https://example.com/api/user/3 https://example.com/api/user/4 https://example.com/api/user/5
$ seq -f "INSERT INTO users (id, username) VALUES (%g, 'user%g');" 1 3
INSERT INTO users (id, username) VALUES (1, 'user1'); INSERT INTO users (id, username) VALUES (2, 'user2'); INSERT INTO users (id, username) VALUES (3, 'user3');
$ seq -s '+' 1 10 | bc
55
$ paste <(seq 1 5) <(seq -f "Item %g" 1 5) | column -t
1 Item 1 2 Item 2 3 Item 3 4 Item 4 5 Item 5
What's happening: Advanced seq usage combining formatting with other tools. First example: Generate URLs with sequential IDs - pipe to xargs curl or wget for batch downloads. Second example: Generate SQL INSERT statements for bulk data loading. Note the limitation: -f only accepts one format specifier, so both ID and username get the same number. For different values, use a loop. Third example: Mathematical expression generation - seq creates "1+2+3+4+5+6+7+8+9+10" which bc evaluates to 55. Fourth example: Process substitution with paste and column to create formatted tables. <(seq 1 5) generates numbers, <(seq -f "Item %g" 1 5) generates labels, paste combines them, column aligns columns. Integration power: Seq's simple output format makes it ideal for piping to other commands - every Unix tool that processes text can work with seq output.
Combine with xargs for powerful batch operations: seq 1 100 | xargs -I{} sh -c 'command_with_number_{}'

Batch API Calls

$ seq 1 100 | xargs -I{} -P 10 curl -s "https://api.example.com/item/{}" > results.json

Fetches items 1-100 with 10 parallel connections.

Complete Options Reference

Option Long Form Description
-f --format=FORMAT Use printf-style floating-point FORMAT (default: %g)
-s --separator=STRING Use STRING to separate numbers (default: \n)
-w --equal-width Equalize width by padding with leading zeros
--help Display help message and exit
--version Output version information and exit

seq vs. Bash Alternatives

Feature seq Brace Expansion {1..10} C-style for ((i=1;i<=10;i++))
Decimal numbers ✅ Yes ❌ No ❌ No (integers only)
Variable ranges ✅ Yes: seq $start $end ❌ No: {$a..$b} doesn't work ✅ Yes
Custom formatting ✅ Yes: -f, -w, -s ❌ No ❌ No
Negative increments ✅ Yes ✅ Yes: {10..1..-2} ✅ Yes
Piping to commands ✅ Easy ⚠️ Needs echo or for loop ⚠️ Needs explicit loop
Performance ⚠️ External process ✅ Built-in, fast ✅ Built-in, fast
Portability ⚠️ Needs seq installed ⚠️ Bash 3.0+ only ⚠️ Bash 2.0+ only
Use brace expansion for simple integer ranges, seq for decimals/formatting/variables, C-style loops for complex conditions.

Best Practices

When and How to Use seq Effectively

  • Use seq when you need:
    • Decimal/floating-point sequences
    • Custom formatting (padding, separators)
    • Variable-based ranges that brace expansion can't handle
    • To pipe sequences to other commands
    • Precise control over output format
  • Prefer alternatives when:
    • Simple integer ranges with literal values: use {1..10}
    • Complex loop conditions: use C-style for loops
    • Performance is critical in tight loops
  • Quoting and word splitting: Use quotes when assigning seq output: numbers="$(seq 1 10)"
  • Large sequences: Be mindful of memory with huge sequences - seq 1 1000000 generates a million numbers
  • Floating-point precision: Be aware of floating-point rounding - seq 0 0.1 1 might not hit 1.0 exactly
  • Test your ranges: Always test with small ranges first, then scale up
  • Use -w for filenames: When generating numbered files, -w ensures proper sorting
  • Combine with other tools: Seq is most powerful when piped to xargs, parallel, awk, etc.

Common Use Cases

Batch File Processing

for i in $(seq -w 1 100); do convert input.jpg -resize "${i}%" output_${i}.jpg done

Resize image to 1%, 2%, ... 100% of original size.

Database Seeding

seq 1 1000 | while read id; do mysql -e "INSERT INTO users VALUES ($id, 'user$id', 'email$id@example.com');" done

Insert 1000 test users into database.

Waiting/Retry Logic

for attempt in $(seq 1 5); do if curl -s http://service.local/health; then break fi echo "Attempt $attempt failed, retrying..." sleep $((attempt * 2)) done

Retry with exponential backoff (2, 4, 6, 8, 10 seconds).

Log Rotation Simulation

for i in $(seq 5 -1 1); do [ -f "app.log.$i" ] && mv "app.log.$i" "app.log.$((i+1))" done mv app.log app.log.1

Rotate logs: app.log.5→6, 4→5, 3→4, 2→3, 1→2, app.log→1

Related Commands

  • yes: Repeat a string infinitely (or until killed)
  • jot: BSD alternative to seq (different syntax)
  • shuf: Generate random permutations (can shuffle seq output)
  • bc: Arbitrary precision calculator for math on sequences
  • awk: Can generate sequences: awk 'BEGIN{for(i=1;i<=10;i++)print i}'
  • perl/python: More powerful sequence/range generation for complex needs
  • xargs: Build and execute commands from standard input (perfect with seq)
  • parallel: GNU parallel for sophisticated parallel processing