I have the following in a script:#!/usr/bin/env bash ...for i in {1..$N}   <loop content>The above doesn't work and is only executed once where i has the value {1..5} (if 5 was provided as argument).If I replace the above with:for i in $(seq 1 1 $N).. then things work as expected. Why is that?
difference between `for i in {1..$N}` and `for i in $(seq 1 1 $N) `
bash
{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>doneOr 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=1while [ $i -le $N ]; do  <loop content>  i=$(($i + 1))doneOr 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.