difference between `for i in {1..$N}` and `for i in $(seq 1 1 $N) `

{1..8} is a form of brace expansion introduced by zsh and supported by recent versions of bash and ksh93. In bash, it is done very early. In particular, it is done before variable expansion.

While {1..8} is valid, {1..$N} is not because $N is not a decimal number, it's the two characters $ and N none of which are decimal digits.

Even if that worked, that would not be very efficient. The shell would have to allocate in memory a list made of the numbers 1 to $N. If $N was 109, that would mean allocating gigabytes of memory.

$(seq "$N") is even less efficient. First, it's not portable. seq is a non-standard GNU command. Then doing $(seq "$N") means starting a new process, executing seq in it, the shell reading its output via a pipe and storing it in memory, then splitting that list (according to $IFS) and attempt to perform filename generation on it.

The space for the list resulting of that splitting and globbing has to be allocated as well.

A more efficient way to do it is to use the ksh for (( )) style of loop (also supported by bash and zsh for decades).

for ((i = 1; i <= N; i++)); do
   <loop content>
done

Or simply write it the portable and standard way, so you don't even have to use bash, and can use your (probably faster/leaner) system's sh:

i=1
while [ "$i" -le "$N" ]; do
  <loop content>
  i=$(($i + 1))
done

Or maybe you can do it more the shell way by avoiding loops altogether. But we'd need to know what you want to do eventually to help there.


@1_CR is right. This is a duplicate. The brace expansions happen first, before the variable, $N, has been expanded. Hence why the first example doesn't work. You're trying to brace expand 1 to a literal $N.

Example

What you're trying to do:

$ N=5
$ echo {1..$N}
{1..5}

When real values are used:

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

Also you're not really comparing apples to apples here. What gives you the impression that {1..$N} is equiv. to $(seq 1 1 $N)?

Other than producing a sequence of numbers, the braces ({..}) and the sub-shell ($(..)`) are 2 completely different notations.

Tags:

Bash