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.