Using Recursion to Search a Directory

BillSoo
03-21-2001, 11:12 AM
A common question I see is "how do I find a file in all subdirectories" or "how do I delete/modify a file in all subdirectories" etc.

The problem is that the directory structure is not fixed. It can be to any depth and have any number of subdirectories per level. So one way to handle this is to use a recursive function. This function will search the *current* subdirectory for the file and then for each subdirectory, it will call another copy of itself to search that subdirectory.

See the attached file for my article and some sample code.

Bill

"I have a plan so cunning you could put a tail on it and call it a weasel!" - Edmund Blackadder

Note: The attached file is actually the code sample in the third post.

BillSoo
04-20-2001, 03:13 PM
A key concept in recursion is that any recursive function can be rewritten as an iterative function and likewise any iterative function can be written recursively.

In general, the recursive version tends to be simpler and easier to understand while the iterative version tends to be more robust and efficient (mainly due to the stack resources that recursive functions require).

So to demonstrate, I rewrote my recursive function to be iterative. As it happens, it is actually a bit simpler. In the recursive version, we needed to declare temporary arrays to hold the results of a DIR function because the DIR function is non re-entrant. This requirement significantly increased the complexity and size of the recursive version. The iterative version below, isn't concerned with re-entrancy problems so is simpler.

The basic algorithm is:
1) start with a beginning directory and add it to a list
2) take a directory off the list
3) look for all files and subdirectories in this directory
4) if you find a directory, add it to the list
5) if you find a file, deal with it.
6) if there are still directories in the list, go to step 2


Sub DirSearch(ByVal StartDir As String)
Dim s As String
Dim currdir As String
Dim dirlist As New Collection

If Right$(StartDir, 1) <> "\" Then StartDir = StartDir & "\"
dirlist.Add StartDir
While dirlist.Count
'remove current directory from directory list
currdir = dirlist.Item(1)
dirlist.Remove 1
'find all files and subdirectories in current, add to list
s = Dir$(currdir, vbDirectory)
While Len(s)
If (s <> ".") And (s <> "..") Then 'get rid of "." and ".."
If GetAttr(currdir & s) = vbDirectory Then 'add the subdirectory
dirlist.Add currdir & s & "\"
Else 'work on the file
Debug.Print currdir & s
End If
End If
s = Dir$
Wend
Wend
End Sub




You can replace the "Debug.Print" statement with any kind of deletion or modification code you want.

BillSoo
08-20-2002, 05:03 PM
Since the original code was lost in the forum shuffle, here is a replacement:

Here is a quick example....I used commas, brackets and the pipe as delimiters. Unfortunately, I think some of these might be valid filename characters.....It might be better to use some other char (maybe tab and CR?) or perhaps store the file as binary.

Option Explicit

Private Sub Command1_Click()
Dim ff As Integer
Dim s As String

ff = FreeFile
Open "c:\map.txt" For Output As #ff
s = FindFiles("c:", "c:\")
Print #ff, s
Close #ff
End Sub

Private Function FindFiles(ByVal sSearchDir As String, ByVal Path As String) As String
'returns a string of all the files and dirs in the sSearchDir as follows:
'(sSearchDir|file,file,file,file)
'where file refers to both files and other dirs. If it is another dir,
'then it will *also* be in this format (dir|file,file,etc)
'path is path to directory being searched, including trailing "\"
Dim aList() As String
Dim nDir As Integer
Dim i As Integer
Dim s As String
Dim fn As String

If Right$(Path, 1) <> "\" Then Path = Path & "\"

'first, find all directories and files
fn = Dir$(Path & "*.*", vbDirectory) 'will find directories AND normal files (not system though)
While Len(fn)
If (fn <> "..") And (fn <> ".") Then
If GetAttr(Path & fn) And vbDirectory Then 'dir
ReDim Preserve aList(nDir)
aList(nDir) = fn
nDir = nDir + 1
Else 'file
s = s & "," & fn
End If
End If
fn = Dir$
Wend

'second, recursively search any directories found
For i = 0 To nDir - 1
s = s & "," & FindFiles(aList(i), Path & aList(i) & "\")
Next i
FindFiles = "(" & sSearchDir & "|" & Mid$(s, 2) & ")"
Erase aList
End Function

EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum