For loops are an essential concept in programming and scripting languages that allow repeating a set of commands iteratively. In Bash shell scripting, for loops provide a handy way to perform operations over collections of data, including arrays, ranges of numbers, strings, command line arguments, and files.
As a beginner exploring Bash scripting, getting a solid grasp on for loops will enable you to start writing scripts for automating tasks and processing data. In this comprehensive guide, we will provide 10 practical examples to demonstrate the most common applications and use cases of Bash for loops.
A Quick Intro to Bash For Loops
Let‘s first cover some for loop basics:
The standard syntax of a for loop in Bash is:
for variable in list_of_items
do
# commands go here
done
This structure allows iterating through each item in list_of_items, executing the loop body with variable set to the current item.
The list_of_items can be any list of strings separated by spaces, an array, output of a command, numeral range, etc. The variable name can be any valid name you choose.
The loop body, marked by do and done, will execute once for each item in the list. You can run commands, manipulate data, and work with the current item value in the loop body.
Now let‘s look at examples applying these concepts.
1. Loop Through an Array
Arrays allow storing multiple elements in a single variable. To loop over array items in Bash:
fruits=("Apple" "Banana" "Orange")
for fruit in "${fruits[@]}";
do
echo "I like ${fruit}!"
done
Quoting "${fruits[@]}" expands the array so each element is iterated over. Inside the loop, we can reference the current element value with $fruit.
This prints:
I like Apple!
I like Banana!
I like Orange!
Accessing the array this way is preferred over just $fruits to properly handle spaces and special characters in values.
You can also loop through indexes and values:
for i in "${!fruits[@]}";
do
echo "${fruits[$i]}"
done
${!array[@]} prints the indexes rather than values. Combined with accessing ${fruits[$i]} by index, this prints:
Apple
Banana
Orange
Being able to iterate through indexes as well as values provides added flexibility.
2. Generate a Number Range
Brace expansions provide a convenient way to define a range of numbers to loop through:
for i in {1..5};
do
echo $i
done
This prints from 1 to 5:
1
2
3
4
5
We can also specify a starting, ending, and increment value:
for i in {0..20..5};
do
echo $i
done
This will iterate from 0 to 20 in steps of 5:
0
5
10
15
20
Number ranges provide an easy way to repeat operations a certain number of times.
3. Read a String By Character
To process a string character by character, we can combine substring expansion with the seq command:
word="Linux"
for i in $(seq 1 ${#word});
do
char=${word:$i-1:1}
echo $char
done
Breaking this down:
${#word}gets the length of the stringseq 1 ${#word}generates numbers from 1 to the length${word:$i-1:1}extracts just 1 char at position$i
This loops through and prints each character:
L
i
n
u
x
With this approach, you can easily parse and manipulate string data programmatically.
4. Process Command Line Arguments
Bash scripts can accept command line arguments passed on invocation using $1, $2, etc.
To loop through all arguments, use $#:
total=0
for arg in "$@";
do
total+=$arg
done
echo "Total: $total"
If you run the script like:
./script.sh 10 20 30
It will print:
Total: 60
This provides an easy way to handle multiple arguments of unknown length.
5. Read a File Line By Line
A common scripting task is processing a file line by line. This can be done cleanly using a while loop:
total=0
while read -r line;
do
total+=$line
done < file.txt
echo "Total: $total"
This iterates through each line of file.txt, adding it to the total.
This approach avoids loading the entire file contents into memory at once.
6. Loop Continuously with an Infinite Loop
You can create an infinite loop with:
while true
do
# Loop forever
done
This construct will loop continuously unless forcibly terminated with CTRL+C.
Infinite loops may arise by accident if a terminating condition fails, causing unexpected behavior. So be careful using while true loops in scripts.
7. Break Out of a Loop
The break statement allows exiting a loop immediately when some condition is met:
for i in {1..10};
do
if [ $i -eq 5 ];
then
break
fi
echo $i
done
This will print 1 to 4, then exit the loop once we hit 5.
Breaking conditional on a match provides an early return without having to process remaining iterations unnecessarily.
8. Skip Iterations with Continue
Similar to break, continue skips the current iteration when a condition matches but keeps looping:
for i in {1..10};
do
if [ $((i % 2)) -eq 0 ];
then
continue
fi
echo $i
done
This prints all odd numbers from 1 to 10, skipping even values.
Continue is useful for efficiently filtering out unwanted elements.
9. Nest Loops
To add additional looping dimensions, nest For loops:
for i in {1..3};
do
echo "i: $i"
for j in {1..3};
do
echo " j: $j"
done
done
The inner loop runs fully on each iteration of the outer loop:
i: 1
j: 1
j: 2
j: 3
i: 2
j: 1
j: 2
j: 3
i: 3
j: 1
j: 2
j: 3
Nesting provides a way to iterate through data organized in matrices and multi-dimensional structures.
10. Loop Through Directories Recursively
We can recurse through subdirectories using globstar **:
shopt -s globstar
for file in **/*.txt;
do
echo $file
done
This will print all text files recursively from the current directory down.
Recursion allows processing files in a directory tree without having to hardcode all possible paths.
Key Takeaways
-
For loops provide a mechanism to iterate through items like arrays, numbers, strings, files, and command line arguments.
-
Special variables like
$@and${array[@]}can be used to conveniently access values. -
Brace expansions like
{1..5}allow quickly defining numeric ranges. -
breakandcontinuestatements add flow control for exiting early or skipping iterations. -
Watch for infinite loops and mistakenly processing more data than intended.
I hope these examples have provided a solid intro to applying for loops for common scripting tasks. Let me know if you have any other favorite loop examples!