Looping over files and directories in Bash Scripting - Time & Space Complexity
When we loop over files and directories in a script, we want to know how the time it takes grows as the number of files grows.
We ask: How does the script's work increase when there are more files?
Analyze the time complexity of the following code snippet.
for file in /path/to/directory/*; do
if [ -f "$file" ]; then
echo "Processing $file"
fi
done
This script loops over each item in a directory and prints a message for each file found.
- Primary operation: Looping over each file and checking if it is a regular file.
- How many times: Once for every item in the directory.
As the number of files increases, the script does more checks and prints more messages.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 checks and prints |
| 100 | About 100 checks and prints |
| 1000 | About 1000 checks and prints |
Pattern observation: The work grows directly with the number of files.
Time Complexity: O(n)
This means the time to finish grows in a straight line as the number of files grows.
[X] Wrong: "The script runs in the same time no matter how many files there are."
[OK] Correct: Each file adds more work because the loop runs once per file, so more files mean more time.
Understanding how loops over files scale helps you write scripts that handle many files efficiently and shows you can think about script performance clearly.
"What if we added a nested loop inside to process each file's lines? How would the time complexity change?"
Practice
for file in *; do echo "$file"; doneSolution
Step 1: Understand the loop variable and pattern
The loop uses*which matches all files and directories in the current folder.Step 2: Analyze the command inside the loop
Each matched item is stored infileand printed withecho.Final Answer:
It prints the names of all files and directories in the current folder. -> Option DQuick Check:
Loop over * prints all names [OK]
- Thinking * matches only files, not directories
- Assuming the loop deletes files
- Believing echo runs only once
Solution
Step 1: Understand the pattern for directories
The pattern*/matches only directories in the current folder because directories end with a slash.Step 2: Check the loop and echo command
The loop iterates over directories and prints their names correctly.Final Answer:
for dir in */; do echo "$dir"; done -> Option CQuick Check:
*/ matches directories only [OK]
- Using * matches files and directories, not only directories
- Using -f to check for directories instead of -d
- Using absolute path /* instead of current folder
file1.txt, file2.txt and a directory docs/?for item in *; do
if [ -f "$item" ]; then
echo "File: $item"
else
echo "Not a file: $item"
fi
doneSolution
Step 1: Identify file and directory checks
The script uses[ -f "$item" ]to check if the item is a file.Step 2: Apply checks to each item
file1.txt and file2.txt are files, so print "File: ..."; docs is a directory, so print "Not a file: docs".Final Answer:
File: file1.txt File: file2.txt Not a file: docs -> Option AQuick Check:
-f true for files only [OK]
- Assuming directories pass -f test
- Confusing -f with -d
- Expecting directory names with trailing slash
for item in *; do
if [ -f "$item" ]; then
echo "$item"
fi
doneSolution
Step 1: Understand the test used
The script uses[ -f "$item" ]which checks if the item is a file, not a directory.Step 2: Identify correct test for directories
To check directories,[ -d "$item" ]should be used instead.Final Answer:
It uses -f to check files instead of -d for directories. -> Option BQuick Check:
Use -d to test directories [OK]
- Confusing -f and -d tests
- Assuming * matches only directories
- Ignoring quotes around variables
Solution
Step 1: Understand the goal
We want to count files only, so we must check each item with[ -f "$item" ].Step 2: Check each option
count=0 for item in *; do if [ -f "$item" ]; then count=$((count + 1)) fi done echo $count correctly loops over all items, increments count only if item is a file, then prints count.Final Answer:
count=0 for item in *; do if [ -f "$item" ]; then count=$((count + 1)) fi done echo $count -> Option AQuick Check:
Use -f test and increment count [OK]
- Counting directories instead of files
- Counting all items without checks
- Using */ pattern which matches directories only
Ready to prove it?
Pass the test and this pattern moves unknown
