So recently someone asked about listing files from several directories but only to a given depth. They were using a DirectoryInfo object, as they probably should, to get a list of files. There was a problem with this however since the constructor of this object only offers a version where you specify no recursion on the sub directories or full recursion and get all the sub directories. This is an all or nothing choice really. But what if you want to go down only so far in the directory hierarchy? Lets say only go down 2 levels of subdirectories looking for matching files? Well there you are going to be a bit stuck unless you code your own. So we will take a look at one possible solution to this problem in this entry of the Programming Underground!
Directories directories when will they ever end? In the vast oceans of directories and files on our hard drives it can be a bit overwhelming sometimes to do a restricted search or listing when you don’t care what the path is. You may not know how far you need to go down. Maybe what you are looking for is at the surface or maybe you are sifting through the silt at the bottom looking for gold. Oh wait I found the city of Codelantis! Just kidding.
As mentioned in the introduction, with the DirectoryInfo object we are only given two choices when specifying the SearchOption parameter enumeration… TopDirectoryOnly or AllDirectories. Come on Microsoft, no middle ground? What if I want only 1 or 2 levels down? Well, that is where our friend recursion can help us. This general design pattern we are going to use is similar to ones you might have seen for traversing any tree like structure. We go down into branches until we hit our leaf nodes (aka the branches that no longer branch) and then move back up.
The only trick to it here is that we need to keep track of our current depth (how far we have gone down into sub branches) and compare that to a limit we specify. This simple comparison will be the condition for our base case. When our depth reaches the depth limit, we have gone far enough. Lets take a look at this…
' Recursive function which keeps moving down the directory tree until a given depth. Public Sub GetFiles(ByVal strFileFilter As String, ByVal strDirectory As String, ByVal intDepthLimit As Integer, ByVal intCurrentDepth As Integer) Dim folderInfo As New DirectoryInfo(strDirectory) ' Is the current depth on this recursion less than our limit? ' If so, find any directories and get into them by calling GetFiles recursively (incrementing depth count) If intCurrentDepth < intDepthLimit Then Dim directories() As DirectoryInfo directories = folderInfo.GetDirectories() For Each fDirectory In directories ' Recursively call ourselves incrementing the depth using the given folder path. GetFiles(strFileFilter, fDirectory.FullName, intDepthLimit, intCurrentDepth + 1) Next End If ' After we can't go further down, add any files which match our filter to listbox (in this case lstFiles) Dim files() As FileInfo files = folderInfo.GetFiles(strFileFilter) For Each fFile In files lstFiles.Items.Add(fFile.FullName) Next End Sub
So when we call this function we are going to supply a file pattern to search for and where to start in the tree. This could be the root directory or it could be anywhere in the hierarchy. The depth limit is how many levels we are going to traverse down and the current depth is how far we are currently down. When these two numbers match, we have hit our “fake” end nodes (aka bottom).
We start by getting the DirectoryInfo object for the given folder. We will use this object to get access to the directories or files of the specified directory. If our current depth is less than the limit, we look for folders. For each folder we are go down into them by calling GetFiles again and incrementing the current depth as well as supplying the current directory. Here we are just trying to find the bottom. We will list our files as we go back up the tree. So we will continue to go down down down the hierarchy until we reach our limit at which point the if statement will be false and we will start listing files that match the pattern by looping through them. Here I dump the full file paths to a listbox called lstFiles, but you could output this anywhere. You could print to screen, a listview, or another control. It is up to you.
After the file listing is done, the function returns to the previous call. From there it will either go to the next sub directory in our directory loop or go onto the second part where it then lists matching files in the directory. After each directory is processed we again move back up and possibly down into another directory.
This whole method may seem a bit confusing to those who are new to the idea of recursion, but if you step through line by line and keep track of where you are at at all times you will eventually see the pattern emerge.
To use this function just call it with the file pattern, the starting directory, limit and current depth (which is usually zero to start).
GetFiles("*.ico", "C:\\myicons", 1, 0)
So with the call above we are looking for files that end with the .ico extension (icon files) and starting in the c:\myicons folder. We want to go only 1 level down and of course starting at 0 (current directory). The result is that we go into each sub folder one level down, reach the bottom, list the files in that folder and then come back up into c:\myicons where we will go into the next folder if there is one or list any ico files int the current directory if there are no more sub folders left.
This method can work in other languages too and the recursive principle applies across languages. Only the syntax will change but the bones of it will still be intact. I hope you find this bit useful and I am sure you will get some use out of it. Play around with it, customize it, store it away in your code library or sleep with it under your pillow. All code here on the Programming Underground is free for the taking to use however you wish. Just don’t steal my dignity!…. or else :gun_bandana: :splat:
Thanks for reading! 🙂