1. Overview
There are various occasions when we might want to loop through all the directories in a given folder. For example, we may want to iterate through all the directories and run a particular command in each folder.
In this tutorial, we’re going to see how we can loop through only the directories in a particular folder using Linux commands. We'll be using the Bash shell in our examples, but these commands may also work in other POSIX shells.
2. The Basic for Loop
Let's start with one of the basic loop constructs provided by Bash. To quickly recap, the for loop is classified as an iteration statement. It takes a list of strings as input and allows code to be repeatedly executed for each item until a certain condition is reached or we reach the end of the list.
Now that we understand the basic for loop construct, in the next subsections, we’ll explain two different ways of looping over directories.
2.1. Pattern Matching Directories Only
We'll start by using a wildcard pattern to match multiple files as input to our for loop:
for dir in */; do echo "$dir" done
Let's explain in more detail what we're doing in the above example:
- We use a standard wildcard glob pattern ‘*' which matches all files. By adding a ‘/' afterward, we'll match only directories
- Then, we assign each directory to the value of a variable dir
- In our simple example, we then execute the echo command between do and done to simply output the value of the variable dir
Then we go back to the top, grab the next directory in the list, and repeat until we reach the end of the list.
Note that although elegant, this solution has one drawback. It assumes we have at least one directory available in the current folder. If no directories are present, the loop will execute once and output ‘*/' which may be undesired.
In the next example, we'll see a solution to combat this.
2.2. Using the Directory File Test Operator
Now, we're going to see how we can use one of the file test operators to determine if the file item in our list is a directory:
for file in *; do if [ -d "$file" ]; then echo "$file" fi done
In this example, we loop through all the files in the current directory. Then using a standard if statement, we can test if the file variable is a directory using the -d flag.
If this condition returns true, we simply output the value of file using the echo command.
3. Using the find Command
In this section, we'll see how we can use the find command to print out a list of the directories inside the current folder:
find . -maxdepth 1 -mindepth 1 -type d -printf '%f\n'
Let's take a look at the command in more detail to understand it properly:
- We begin with a ‘.' which is used to represent the current directory
- The maxdepth parameter represents the level of directories to descend to from the starting point
- We then use the mindepth parameter with a value of 1 to process all files except the starting point – this means that ‘.' won't be included in the result.
- The -type d parameter is used to only include directories
- Finally, we use printf to print only the folder's name, plus a new line for each result.
This example serves as a simple demonstration, but in reality, we probably want to do more than just print out the names of directories. In the next section, we'll see a variation on the above.
4. Combining find and a while read Loop
In this penultimate example, we'll see how we can use the find command as we did in the last section but this time combining it with a while read loop to execute a command for each directory we find.
As per our for loop example, we will simply echo the name of the folder:
find . -maxdepth 1 -mindepth 1 -type d | while read dir; do echo "$dir" done
In this example instead of using the printf parameter to output the folder name, we pipe each of the results into a while loop. We assign the value of each directory to a variable called dir and then simply echo the value of this variable.
5. Using find and the exec Parameter
In this final example, we'll explore an arguably more elegant and concise solution for executing a command for each directory we find.
As per the previous examples, we will simply echo the name of the folder but this time making use of the -exec parameter:
find . -maxdepth 1 -type d -exec echo {} \;
Using the -exec action, we can run the specified command on the selected files. In our example, echo will substitute {} with the filename(s) found. The last part of the command which is an escaped ‘;' simply means that a single echo command for each file is executed.
6. Conclusion
In this quick tutorial, we’ve described a few ways that help us loop through directories.
First, we explored the basic for loop using standard file pattern wildcards. Later, we added a directory file test. Then, we showed how we can achieve similar results using the find command.
As always, the full source code of the article is available over on GitHub.