It's a long-established truism that, "you can't use VB's Dir function recursively." Right? Wrong! You most certainly can use it within recursive functions, but if you call a function recursively from within a Dir loop you are asking for serious trouble. The reason for this is that Dir uses a single hFindFile handle with a series of FindFirstFile / FindNextFile / FindClose API calls. The design is simple and elegant, and you're stuck with its limitations.
So what can you do to drill down recursively through a folder hierarchy, looking for all (or specific) files under a given location? Your choices come down to writing your own version of Dir, with each recursive call starting a new call to FindFirstFile, and storing a unique hFileFile handle. Or, using Dir smartly.
To use Dir recursively, the secret is to run two loops within each level. The first Dir loop scans for all matching files and folders. Folders are stored in one array, files in another. When that initial loop is completed, run another loop passing each element of the Folders array to this same function. Simple concept, horribly botched time and time again.
The sample you can download from this page takes the concept a step farther, and encapsulates a recursive, multi-filespec search into an event-raising class module. Drop this into a project, and you can use it as simply as this:
Private WithEvents dd As CDirDrill Private Sub Command1_Click() dd.Folder = CurDir$ dd.Pattern = "*.bas;*.cls;*.frm;*.ctl" dd.BeginSearch End Sub Private Sub dd_Done(ByVal TotalFiles As Long, ByVal TotalFolders As Long) Debug.Print "Found "; TotalFiles; " files in "; TotalFolders; " folders." End Sub Private Sub dd_NewFile(ByVal FileSpec As String, Cancel As Boolean) ' Show that we found one... Debug.Print Space$(5) & dd.ExtractName(FileSpec) ' Do any other processing here... End Sub Private Sub dd_NewFolder(ByVal FolderSpec As String, Cancel As Boolean) Debug.Print FolderSpec End Sub
Too easy? I think so.
Oh, this sample also includes a bonus module that recreates several of the new-to-VB6 string functions, so you can use them in VB5 as well. If you've become used to Join, Split, InstrRev, Replace, and/or Reverse in VB6, now you can use them in VB5 too! These functions were "originally stolen" from freevbcode.com, and have been heavily modified over the years. If this topic interests you, you'll probably really like the vbspeed site, for it's intensively anal optimizations of these and many other functions.
This sample hasn't been published anywhere except here on this website, but first rights to such publication are jealously guarded - you have been warned. <g>
No APIs were harmed in the making of this sample.
Please, enjoy and learn from this sample. Include its code within your own projects, if you wish. But, in order to insure only the most recent code is available to all, I ask that you don't share the sample by any form of mass distribution.
Download DirDrill.zip, 7Kb, Last Updated: Monday, June 18, 2007
The following resources may also be of interest:
- Streams - Enumerate, delete, or otherwise manipulate Alternate Data Streams in any NTFS file.