Difference between revisions of "Searching directories recursively"

From HashVB
Jump to: navigation, search
m (Tidied up the code sample)
Line 1: Line 1:
{{VB6}}
 
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.
 

Revision as of 16:25, 31 December 2005