Difference between revisions of "Searching directories recursively"
From HashVB
(No difference)
|
Revision as of 01:08, 20 October 2005
This is a useful technique that allows you to search for files and build directory trees a lot faster than the intrinsic VB methods allow.
It involves the use of the file finding APIs, the declarations for which are as follows:
Private Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" (ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA" (ByVal lpFileName As String) As Long
Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long
Const MAX_PATH = 260
Const INVALID_HANDLE_VALUE = -1
Const FILE_ATTRIBUTE_ARCHIVE = &H20
Const FILE_ATTRIBUTE_DIRECTORY = &H10
Const FILE_ATTRIBUTE_HIDDEN = &H2
Const FILE_ATTRIBUTE_NORMAL = &H80
Const FILE_ATTRIBUTE_READONLY = &H1
Const FILE_ATTRIBUTE_SYSTEM = &H4
Const FILE_ATTRIBUTE_TEMPORARY = &H100
Const MAXDWORD As Long = &HFFFFFFFF
Private Type FILETIME
dwLowDateTime As Long
dwHighDateTime As Long
End Type
Private Type WIN32_FIND_DATA
dwFileAttributes As Long
ftCreationTime As FILETIME
ftLastAccessTime As FILETIME
ftLastWriteTime As FILETIME
nFileSizeHigh As Long
nFileSizeLow As Long
dwReserved0 As Long
dwReserved1 As Long
cFileName As String * MAX_PATH
cAlternate As String * 14
End Type
NOTE: I have also included all the other necessary declarations for using the code below.
The code that will actually recurse through the directories goes like this:
Public Function RecurseCopyDirs(ByVal StartDir As String, ByVal DestDir As String) As Double
Dim s As String
Dim hSearch As Long
Dim WFD As WIN32_FIND_DATA
Dim Cont As Integer
Dim DirSize As Double
If Right$(StartDir, 1) <> "\" Then StartDir = StartDir & "\"
hSearch = FindFirstFile(StartDir & "*", WFD)
If hSearch <> INVALID_HANDLE_VALUE Then
Cont = True
Do While Cont
s = StripNulls(WFD.cFileName)
'-- Ignore the current and encompassing directories.
If (s <> ".") And (s <> "..") Then
'-- Check if it's a directory
If GetFileAttributes(StartDir & s) And FILE_ATTRIBUTE_DIRECTORY Then
Debug.Print "DIR", StartDir & s
DirSize = DirSize + RecurseCopyDirs(StartDir & s)
Else
Debug.Print "FILE", StartDir & s
DirSize = DirSize + CDbl(CStr(WFD.nFileSizeHigh)) * (MAXDWORD + 1) + WFD.nFileSizeLow
End If
End If
Cont = FindNextFile(hSearch, WFD)
Loop
Cont = FindClose(hSearch)
End If
RecurseCopyDirs = DirSize
End Function
Function StripNulls(OriginalStr As String) As String
If (InStr(OriginalStr, Chr(0)) > 0) Then
OriginalStr = Left(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)
End If
StripNulls = OriginalStr
End Function
This will print all of the files, directories and subdirectories under the directory that you provide it with to the Immediate window, and, as an added bonus, returns the total size of the files in the directory tree.
Enjoy.