Suppose you wanna iterate over a number of things, such as the sequence 1..10, or the directory listing (the output of the ls command), or lines in a file. To do this in Bash, use the following syntax (where WORD and LIST are according to the definitions in the Bash man page).

for k in WORDs ; do LIST; done

You have options on how to specify WORDs, including expansions, substitutions, or writing them out by hand.

Let’s start with expansions. You can use a brace expansion, which are evaluated before any commands are executed

$ echo {1..10}
1 2 3 4 5 6 7 8 9 10

So, the following statements are equivelant:

for k in {1..10}; do echo $k; done
for k in 1 2 3 4 5 6 7 8 9 10; do echo $k; done

Alternatively, use the output of the seq command with with command substitution, where the value of the command is substituted in place of the command

$ seq 10
1
2
3
4
5
6
7
8
9
10

$ echo  $(seq 10)
1 2 3 4 5 6 7 8 9 10

So we can then say, again equivelant to the above,

for k in $(seq 10); do echo $k; done

Let’s take another example, iterating over the directory listing. It can be done with command substitution this way

for k in $(ls); do echo $k; done 

and can be done with a wildcard expansion (another kind of expansion) this way

for k in *; do echo $k; done

Another substitution is process substitution, which enables referring to the output of a command as a filename. So for example, if the syntax of the command is

$ cat FILE

Where file contains a list of numbers obtained using redirection with seq 10 > FILE. You can use

$ cat <(seq 10)

The above is redundant since we can just write seq 10 to show the result. Another one, let’s read a file line by line and echo it to the screen

while read line; do echo $line; done < <(seq 10)

what happens when you echo a file name?

$ echo <(seq 10)
/proc/self/fd/63

Here is a better usage of process substitution, since its asynchronous, lets use it with the curl command

$ grep bash <(curl https://azizcodes.github.io)

Here is another quick overview.