Iterate over files in Linux using for loop
Looping over files in Linux is a handy skill. It helps you manage and organize your files more easily. In this tutorial, we’ll learn how to use Bash to loop through files.
We’ll look at how to use for loop to iterate over regular files, files with spaces in their names, directories, ignore case sensitivity, and much more.
By the end of this tutorial, you’ll learn how to loop over different types of files and patterns.
- 1 The for file in /path/to/files/* Pattern
- 2 Looping Over Regular Files
- 3 The find Command with for (Recursive looping)
- 4 Handling File Names with Special Characters
- 5 Looping Over Directories
- 6 Looping Over Symbolic Links
- 7 Mixed File Types
- 8 Looping Over Specific File Extensions
- 9 Case Sensitivity and Matching
- 10 Ignoring Hidden Files
- 11 Using Regular Expressions
The for file in /path/to/files/* Pattern
Command:
for file in /path/to/files/*; do echo "$file" done
Output:
/path/to/files/file1.txt /path/to/files/file2.jpg /path/to/files/file3.doc ...
This script uses the shell globbing mechanism.
The /path/to/files/*
pattern matches every file in the directory /path/to/files/
.
For each file in the directory, the echo
command prints the full path to the console.
The loop continues until all files have been processed. The result is a list of every file within the specified directory.
Looping Over Regular Files
There are various wildcard characters in Bash that can help you target specific file types or patterns. Let’s explore some of the most commonly used ones.
Using (*)
Command:
for file in /path/to/files/*.txt; do echo "$file" done
Output:
/path/to/files/file1.txt /path/to/files/file2.txt ...
The *
character matches any string, allowing you to filter files based on a specific extension or naming convention.
Using (?)
Command:
for file in /path/to/files/file?.txt; do echo "$file" done
Output:
/path/to/files/file1.txt /path/to/files/file2.txt ...
The ?
character matches any single character, providing a way to target files with a specific naming structure.
Using ([])
Command:
for file in /path/to/files/file[1-3].txt; do echo "$file" done
Output:
/path/to/files/file1.txt /path/to/files/file2.txt /path/to/files/file3.txt
By using []
, you can match specific characters or a range of characters, granting even more precision in file targeting.
The find Command with for (Recursive looping)
Linux find command allows you to search for files or directories based on various criteria.
By combining find
with the for
loop, you can effectively iterate over files in nested directories.
Command:
for file in $(find /path/to/files/ -type f); do echo "$file" done
Output:
/path/to/files/subdir/file4.txt /path/to/files/file1.txt /path/to/files/file3.doc ...
The find
command is used to retrieve all regular files (-type f
) within /path/to/files/
.
The results from find
are then processed by the for
loop. The echo
command prints each file’s full path to the console.
The loop continues until all files found by find
are processed.
Handling File Names with Special Characters
Special characters, especially spaces, can pose problems when looping through files in Bash. Let’s address this challenge.
Command:
IFS=$'\n' for file in $(find /path/to/files/ -type f); do echo "$file" done
Output:
/path/to/files/My Document.txt /path/to/files/Program #123.log ...
By setting the Internal Field Separator (IFS) to a newline character.
We instruct the shell to treat only newlines as delimiters, ignoring spaces.
This ensures filenames with spaces are not split into multiple entries.
As a result, the for
loop can iterate over filenames with spaces or other special characters without any issues.
Looping Over Directories
Sometimes, instead of files, you’ll need to loop over directories. Here’s how to do it:
Command:
for dir in /path/to/files/*/; do echo "$dir" done
Output:
/path/to/files/directory1/ /path/to/files/directory2/ ...
The trailing /
after the *
wildcard ensures you’re matching only directories.
Each matched directory’s path is printed to the console. The loop continues until all directories in the specified location are processed.
Looping Over Symbolic Links
Symbolic links (or symlinks) are essentially references to other files or directories.
Command:
for link in $(find /path/to/files/ -type l); do echo "$link" done
Output:
/path/to/files/link_to_file1.txt /path/to/files/link_to_directory2/ ...
We use the find
command with the -type l
option to target only symbolic links.
The results from find
are processed by the for
loop. Each symlink’s path is printed to the console.
Mixed File Types
You can loop over a mixture of regular files, directories, and symbolic links. Let’s see how this can be done.
Command:
for item in /path/to/files/*; do if [[ -f "$item" ]]; then echo "File: $item" elif [[ -d "$item" ]]; then echo "Directory: $item" elif [[ -L "$item" ]]; then echo "Symlink: $item" fi done
Output:
File: /path/to/files/file1.txt Directory: /path/to/files/directory1/ Symlink: /path/to/files/link_to_file1.txt ...
The loop iterates over all items in the directory. Conditionals (if
, elif
) are used to determine the type of each item.
The type and path of the item are printed based on their classification.
Looping Over Specific File Extensions
At times, you’ll need to loop over files with specific extensions. This is often the case when working with certain types of data or file formats.
Command:
for file in /path/to/files/*.{txt,jpg,png}; do echo "$file" done
Output:
/path/to/files/file1.txt /path/to/files/image1.jpg /path/to/files/picture1.png ...
The curly braces {}
allow you to match multiple file extensions at once.
Each file matching the extensions .txt
, .jpg
, and .png
is printed to the console.
The loop proceeds until all matching files are processed.
Case Sensitivity and Matching
By default, Bash is case-sensitive. However, there are scenarios where you want to loop over files regardless of their case.
Command:
shopt -s nocaseglob
for file in /path/to/files/*.[Tt][Xx][Tt]; do
echo "$file"
done
shopt -u nocaseglob
Output:
/path/to/files/file1.TXT /path/to/files/file2.txt ...
The shopt -s nocaseglob
command is used to turn off case sensitivity for globbing.
The pattern *.[Tt][Xx][Tt]
matches both lowercase and uppercase variations of .txt
files.
Each matching file’s path is printed to the console. Finally, return to the default case sensitivity using shopt -u nocaseglob
.
Ignoring Hidden Files
If you want to process files while excluding hidden ones. Here’s how to achieve this:
Command:
for file in /path/to/files/*; do if [[ ! $file =~ ^..* ]]; then echo "$file" fi done
Output:
/path/to/files/file1.txt /path/to/files/image1.jpg ...
The loop iterates over all items in the directory. The if
statement checks if the file name does not start with a dot (.
).
If the file isn’t hidden, its path is printed to the console.
Using Regular Expressions
Bash supports regular expressions, providing a powerful means for advanced pattern matching.
Command:
for file in /path/to/files/*; do if [[ $file =~ ^/path/to/files/file[0-9]+.txt$ ]]; then echo "$file" fi done
Output:
/path/to/files/file1.txt /path/to/files/file23.txt ...
The loop iterates over every item in /path/to/files/
.
The if
statement checks if the file matches the regex pattern ^/path/to/files/file[0-9]+\.txt$
.
Files named file
followed by one or more digits and ending in .txt
match this pattern.
Mokhtar is the founder of LikeGeeks.com. He is a seasoned technologist and accomplished author, with expertise in Linux system administration and Python development. Since 2010, Mokhtar has built an impressive career, transitioning from system administration to Python development in 2015. His work spans large corporations to freelance clients around the globe. Alongside his technical work, Mokhtar has authored some insightful books in his field. Known for his innovative solutions, meticulous attention to detail, and high-quality work, Mokhtar continually seeks new challenges within the dynamic field of technology.