Shell Script Flow Control (For Loops)
Shell Script Flow Control (For Loops)
In Shell scripting, the for loop is one of the most fundamental control structures for handling repetitive tasks and iterating over collections. It allows a program to automatically execute a block of code based on specific conditions or data sources. Unlike high-level languages such as C, the syntax of the Shell's for loop is more concise and semantic, primarily divided into two forms: sequential iteration and list traversal. Mastering both modes is essential for writing efficient Shell scripts.
This form of loop is primarily used for counting operations on numbers or specific ranges. Its basic syntax structure is for var in {start..end}, where var stores the value of the current iteration, and {start..end} defines the range of values to be generated.
Basic Usage Example
Suppose we need to calculate the sum from 1 to 5; the following script can be used:
sum=0
for i in {1..5}
do
sum=$((sum + i))
done
echo "Total sum is: $sum"
In this example, the variable i takes values sequentially as 1, 2, 3, 4, and 5. After each loop iteration completes, the value of i is automatically updated to the next number in the sequence. Through the arithmetic expansion command $(( )), we can conveniently perform mathematical operations. This writing style not only makes the logic clear but also avoids the tediousness of manually maintaining a counter variable.
List-Based For Loops
When traversing a specific set of files, paths, or custom strings, list-based for loops are more commonly used. Its syntax form is for item in list, where list can be a sequence of space-separated words or the output of a command (achieved through redirection).
Traversing File Lists
This is one of the most common application scenarios in Shell scripting. For example, to process all text files in the current directory, you can combine it with wildcards:
for file in *.txt; do
echo "Processing file: $file"
# Execute specific file operations here, such as copying, moving, or deleting
done
If the list contains special characters (such as spaces or quotes), using * directly may cause errors. In such cases, it is recommended to use the find command combined with redirection to build the list, ensuring safety:
for file in $(find . -name "*.txt"); do
echo "Found file: $file"
done
Traversing Custom Strings
In addition to files and numbers, for loops can also be used to split and process strings. For example, if you want to convert a comma-separated list into an array format for individual processing:
colors="red,green,blue"
for color in $colors; do
echo "Current color: $color"
done
Note that the above method carries risks when processing strings containing spaces. It is generally recommended to use the IFS (Internal Field Separator) variable to optimize input parsing.
Conditional Control and Exit in Loops
In actual development, it is often necessary to execute different logic based on dynamic conditions inside a loop or terminate the loop early. Shell provides structures such as if and while to meet this requirement, while also supporting break and continue statements within the loop body (although support for continue may be limited in some older Shells, it is fully supported in Bash).
Conditional Judgment Example
If a file does not exist or lacks permissions during traversal, you can immediately skip that iteration:
for file in *.log; do
if [ ! -r "$file" ]; then
echo "Warning: Cannot read $file, skipping"
continue
fi
# Execute normal processing logic
done
Early Exit Example
When a specific condition is met, using break can immediately end the entire loop process, avoiding unnecessary resource consumption:
count=0
for i in {1..20}
do
count=$((count + 1))
if [ $count -ge 5 ]; then
echo "Target quantity reached, exiting loop"
break
fi
done
Best Practices and Precautions
Following good coding habits when using for loops can significantly enhance the robustness and maintainability of scripts. First, ensure all variables used are initialized before the loop begins to prevent errors related to undefined variables. Second, for list traversal, avoid directly using $() command substitution to generate lists, as this may lead to issues with subshell execution environments; instead, recommend using mapfile (Bash 4.4+) or readarray to store command output in an array before looping.
Additionally, when performing complex file operations inside a loop, always check return values and handle potential error states. Finally, for performance-sensitive scenarios, avoid executing long-running external commands within the loop body; instead, try to internalize calculation logic to improve efficiency. By reasonably applying for loops and their related control structures, developers can construct automated scripts with rigorous logic and high execution efficiency.