How to Write Bash FOR-loops
A good way to execute a sequence of commands is to write them into a "script file". A script file is simply a text file, typically with the file name extension ".sh", that contains a sequence of statements to be executed. For example, when executed, the following procedure would print the number 1 through 9 on the screen:
#!/bin/bashfor count in 1 2 3 4 5 6 7 8 9doecho "$count"done
Assuming this code is written to a file called "script1.sh", you can execute it by first making it executable, for example withchmod 775 script1.sh
And then executing it with:
./script1.shThe first line in the script (#!/bin/bash) tells the shell which program to use for execution.
The structure of the "for" statement is "for ... in ... do ... done". In the above example "count" is a variable which is assigned each of the values in the list "1 2 3 4 5 6 7 8 9". For each value, the statements between "do" an "done" are executed once. The value of the variable is accessed using the notation "$count". That is, the variable name preceded with a dollar sign.
So, on the first iteration the $count has the value "1", on the second iteration it has the value "2", etc. The echo statement means that the string to the right (its "argument") is printed on the next line on the shell window. Therefore the output of the above bash program would be:
123456789
Bash for-loops are frequently used to perform an operation on a set of files. For example, if you wanted to uncompress all files with extension "bz2" in the directory /home/jdoe/data/ using the utility bunzip2 you could use the following bash script:
#!/bin/bashFILES=/home/jdoe/data/*.bz2for file in $FILESdobunzip2 $filedone
In the statement "FILES=/home/jdoe/data/*.bz2" the variable "FILES" is assigned the list of files in directory (folder) "/home/jdoe/data/", whose name ends with ".bz2". The "*" (wild card character) stands for any sequence of characters.In the for-statement "file" is used as the name of the loop variable, which is assigned each of the file names in the list assigned to "FILES". The body of the for-loop (the statements between the "do" and the "done") is executed once for each file name.
The following example illustrates the use of "ranges" in a for-loop:
#!/bin/bashfor count in {1..9}doecho "$count"done
The expression "{1..9}" is a shorthand for the list "1 2 3 4 5 6 7 8 9". So this program does essentially the same the one above.The range notation has a variant that allows you to specify the step size. In the following example the loop variable is increased by 3 on each iteration:
#!/bin/bashfor count in {1..10..3}doecho "$count"done
So the output would be:
14710
In some cases it is more suitable to use a while-loop instead of a for-loop. The following example does essentially the same the for-loop above:
#!/bin/bashcount=1while [[ $count -le 9 ]]doecho "$count"(( count++ ))done
Although the while-statement is not quite as elegant as a for-loop, it gives you more flexibility for specifying the termination condition. For example you can make the previous script an infinite loop by omitting the increment statement "(( count++ ))":
#!/bin/bashcount=1while [[ $count -le 9 ]]doecho "$count"sleep 1done
The sleep 1 statement pauses the execution for 1 second on each iteration. Use "Ctrl-C" to terminate the process.