Linux seq Command Deep Dive: From Number Sequences to Batch Task Automation#

Published: May 9, 2026 11:50

Introduction#

In daily Linux operations, batch processing is inevitable. Renaming 100 files, creating 50 directories, generating test data—these seemingly simple tasks become tedious if done manually. The seq command is designed exactly for these scenarios: it generates number sequences with arbitrary rules, enabling batch automation when combined with command substitution.

As a loyal user of JsonKit toolkit, you might be accustomed to the convenience of online tools. But on the server side, lightweight commands like seq remain indispensable efficiency tools. Today let’s dive deep into seq’s implementation principles and practical techniques.

Core Principle: Formatted Number Output#

The essence of seq is a number formatter. Its core logic is straightforward:

// Pseudocode showing core logic
for (i = start; i <= end; i += increment) {
    print(format(i));
}

But the devil is in the details—seq handles floating-point numbers, not integers. This means:

# Integer sequence
seq 1 5
# Output: 1 2 3 4 5

# Floating-point sequence
seq 1 0.5 3
# Output: 1.0 1.5 2.0 2.5 3.0

In the source code, seq uses strtod() to convert strings to doubles, then accumulates with a for loop. There’s a precision trap here:

# Precision loss example
seq 1 0.1 2 | tail -3
# Output: 1.8 1.9 2.0 (seems normal)
# But actually might be: 1.8000000000000001 ...

That’s why seq introduced the -f formatting parameter, using printf style to control precision:

seq -f "%.1f" 1 0.1 2
# Force 1 decimal place, avoiding precision loss

Three Key Parameters Explained#

1. -s Custom Separator#

Default uses newline as separator, but -s can change it to any character:

# Generate comma-separated list
seq -s, 1 10
# Output: 1,2,3,4,5,6,7,8,9,10

# Generate space-separated (for for loops)
seq -s' ' 1 5
# Output: 1 2 3 4 5

2. -w Equal Width with Zero Padding#

This is one of the most practical parameters, automatically padding zeros to align digit counts:

seq -w 1 10
# Output: 01 02 03 ... 09 10

# Generate numbered filenames
for i in $(seq -w 1 100); do
    touch "file_$i.txt"
done
# Creates: file_01.txt ... file_100.txt

Implementation: calculate the maximum digit count of start and end numbers, format with %0Nd.

3. -f Format String#

Full printf format support, extremely flexible:

# Generate filenames with prefix
seq -f "img_%03d.jpg" 1 20
# Output: img_001.jpg img_002.jpg ... img_020.jpg

# Generate date list
seq -f "2026-01-%02d" 1 31
# Output: 2026-01-01 ... 2026-01-31

Practical Scenarios#

Scenario 1: Batch File Renaming#

# Rename img_1.jpg ~ img_100.jpg to photo_001.jpg ~ photo_100.jpg
for i in $(seq -w 1 100); do
    mv "img_$i.jpg" "photo_$i.jpg"
done

Scenario 2: Create Test Data#

# Generate 100 test files, each 1MB
for i in $(seq -w 1 100); do
    dd if=/dev/zero of="test_$i.bin" bs=1M count=1 2>/dev/null
done

Scenario 3: Batch Download#

# Download paginated images
for i in $(seq -f "%03g" 1 50); do
    wget "https://example.com/image_$i.jpg"
done

Scenario 4: Generate SQL Test Data#

# Insert 1000 test records
for i in $(seq 1 1000); do
    echo "INSERT INTO users (id, name) VALUES ($i, 'user_$i');"
done | mysql -u root -p test_db

Performance Optimization: seq vs Brace Expansion#

Bash’s brace expansion can also generate sequences:

# Brace expansion
echo {1..10}
# Output: 1 2 3 4 5 6 7 8 9 10

# seq command
seq 1 10
# Output: 1 2 3 4 5 6 7 8 9 10

Performance comparison (generating 1 million numbers):

time echo {1..1000000} > /dev/null
# real: 0.02s

time seq 1 1000000 > /dev/null
# real: 0.15s

Brace expansion is faster, but has limitations:

  • No floating-point support
  • No custom step size (e.g., 1 to 10 every 2)
  • No formatting support

So: Use braces for simple sequences, use seq for complex needs.

Edge Cases and Pitfalls#

1. Negative Step#

seq 10 -1 1
# Output: 10 9 8 ... 2 1

seq 10 1
# No output (step defaults to 1, but 10+1 > endpoint)

2. Floating-Point Precision Issues#

# Wrong example
seq 0 0.1 1 | wc -l
# Might output 11 instead of 10 (precision accumulation causes extra loop)

# Correct approach
seq -f "%.1f" 0 0.1 1 | wc -l
# Stable output: 10

3. Large Number Handling#

seq 1 1000000000 > huge.txt
# Generates 1GB+ file, might exhaust disk

# Safer approach: pipe processing
seq 1 1000000000 | head -1000

Web Implementation: Browser-Based seq#

In the JsonKit tool ecosystem, we can implement a similar number sequence generator using JavaScript:

function generateSeq(start, end, step = 1, format = null, separator = '\n') {
    const result = [];
    const maxDecimals = Math.max(
        (step.toString().split('.')[1] || '').length,
        (start.toString().split('.')[1] || '').length
    );
    
    for (let i = start; step > 0 ? i <= end : i >= end; i += step) {
        let value = i.toFixed(maxDecimals);
        if (format) {
            value = format.replace(/%0?(\d+)?d/g, (match, width) => {
                return i.toString().padStart(parseInt(width) || 0, '0');
            });
        }
        result.push(value);
    }
    
    return result.join(separator);
}

// Usage example
generateSeq(1, 10, 2, 'file_%02d.txt', '\n');
// Output:
// file_01.txt
// file_03.txt
// file_05.txt
// file_07.txt
// file_09.txt

Summary#

seq seems simple, but it’s an efficiency multiplier in batch operation scenarios. Its core value lies in:

  1. Formatted Output: -f parameter enables any format
  2. Equal Width Padding: -w parameter auto-aligns
  3. Flexible Step: Supports floating-point and negative steps
  4. Pipe-Friendly: Seamlessly integrates into command chains

Next time you encounter a batch task, think: can seq simplify it? Don’t write loops for things one command can handle.


Related Tools: