You are currently offline, waiting for your internet to reconnect

How To Search Directories to Find or List Files

This article was previously published under Q185476
SUMMARY
When looking for files, it is often necessary to search throughsubdirectories. This article demonstrates two methods for recursivelysearching directories and retrieving file information.
MORE INFORMATION
While Visual Basic provides methods for retrieving information about filesand directories, you may also use Windows API functions for these tasks.Using the API is not faster than the built in methods, but the two methodswork a little differently. So, this article demonstrates both techniquesfor retrieving this information. If you test both methods, try using thesame starting path and search string. You should get similar results.

Please note that the following examples do not include full error trapping,but Method 2 does catch a special case where the VB GetAttr() functionfails on Pagefile.sys, which is the Windows NT virtual memory paging file.Also, depending on the search string, the API version lists and countsdirectory names by default, where the VB version does not.Please note that the following examples do not include full error trapping,but Method 2 does catch a special case where the VB GetAttr() functionfails on Pagefile.sys, which is the Windows NT virtual memory paging file.The only difference in results between these two methods is that the VBcode does not return the file create dates.

Method 1: Using the Windows API

  1. Start a new Standard EXE project in Visual Basic. Form1 is created by default.
  2. Add a CommandButton named Command1, four TextBoxes named Text1, Text2, Text3 and Text4 and a ListBox to Form1.
  3. Add a Module from the Projects menu and insert the following:
       Declare Function FindFirstFile Lib "kernel32" Alias _   "FindFirstFileA" (ByVal lpFileName As String, lpFindFileData _   As WIN32_FIND_DATA) As Long   Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" _   (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long   Declare Function GetFileAttributes Lib "kernel32" Alias _   "GetFileAttributesA" (ByVal lpFileName As String) As Long   Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) _   As Long   Declare Function FileTimeToLocalFileTime Lib "kernel32" _   (lpFileTime As FILETIME, lpLocalFileTime As FILETIME) As Long        Declare Function FileTimeToSystemTime Lib "kernel32" _   (lpFileTime As FILETIME, lpSystemTime As SYSTEMTIME) As Long   Public Const MAX_PATH = 260   Public Const MAXDWORD = &HFFFF   Public Const INVALID_HANDLE_VALUE = -1   Public Const FILE_ATTRIBUTE_ARCHIVE = &H20   Public Const FILE_ATTRIBUTE_DIRECTORY = &H10   Public Const FILE_ATTRIBUTE_HIDDEN = &H2   Public Const FILE_ATTRIBUTE_NORMAL = &H80   Public Const FILE_ATTRIBUTE_READONLY = &H1   Public Const FILE_ATTRIBUTE_SYSTEM = &H4   Public Const FILE_ATTRIBUTE_TEMPORARY = &H100   Type FILETIME     dwLowDateTime As Long     dwHighDateTime As Long   End Type   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   Type SYSTEMTIME     wYear As Integer     wMonth As Integer     wDayOfWeek As Integer     wDay As Integer     wHour As Integer     wMinute As Integer     wSecond As Integer     wMilliseconds As Integer   End Type   Public 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					
  4. Copy the following code into Form1's module:
       Option Explicit   Function FindFilesAPI(path As String, SearchStr As String, _    FileCount As Integer, DirCount As Integer)   Dim FileName As String   ' Walking filename variable...   Dim DirName As String    ' SubDirectory Name   Dim dirNames() As String ' Buffer for directory name entries   Dim nDir As Integer   ' Number of directories in this path   Dim i As Integer      ' For-loop counter...   Dim hSearch As Long   ' Search Handle   Dim WFD As WIN32_FIND_DATA   Dim Cont As Integer   Dim FT As FILETIME   Dim ST As SYSTEMTIME   Dim DateCStr As String, DateMStr As String        If Right(path, 1) <> "\" Then path = path & "\"   ' Search for subdirectories.   nDir = 0   ReDim dirNames(nDir)   Cont = True   hSearch = FindFirstFile(path & "*", WFD)   If hSearch <> INVALID_HANDLE_VALUE Then      Do While Cont         DirName = StripNulls(WFD.cFileName)         ' Ignore the current and encompassing directories.         If (DirName <> ".") And (DirName <> "..") Then            ' Check for directory with bitwise comparison.            If GetFileAttributes(path & DirName) And _             FILE_ATTRIBUTE_DIRECTORY Then               dirNames(nDir) = DirName               DirCount = DirCount + 1               nDir = nDir + 1               ReDim Preserve dirNames(nDir)               ' Uncomment the next line to list directories               'List1.AddItem path & FileName            End If         End If         Cont = FindNextFile(hSearch, WFD)  ' Get next subdirectory.      Loop      Cont = FindClose(hSearch)   End If   ' Walk through this directory and sum file sizes.   hSearch = FindFirstFile(path & SearchStr, WFD)   Cont = True   If hSearch <> INVALID_HANDLE_VALUE Then      While Cont         FileName = StripNulls(WFD.cFileName)            If (FileName <> ".") And (FileName <> "..") And _              ((GetFileAttributes(path & FileName) And _               FILE_ATTRIBUTE_DIRECTORY) <> FILE_ATTRIBUTE_DIRECTORY) Then            FindFilesAPI = FindFilesAPI + (WFD.nFileSizeHigh * _             MAXDWORD) + WFD.nFileSizeLow            FileCount = FileCount + 1            ' To list files w/o dates, uncomment the next line            ' and remove or Comment the lines down to End If            'List1.AddItem path & FileName                       ' Include Creation date...           FileTimeToLocalFileTime WFD.ftCreationTime, FT           FileTimeToSystemTime FT, ST           DateCStr = ST.wMonth & "/" & ST.wDay & "/" & ST.wYear & _              " " & ST.wHour & ":" & ST.wMinute & ":" & ST.wSecond           ' and Last Modified Date           FileTimeToLocalFileTime WFD.ftLastWriteTime, FT           FileTimeToSystemTime FT, ST           DateMStr = ST.wMonth & "/" & ST.wDay & "/" & ST.wYear & _              " " & ST.wHour & ":" & ST.wMinute & ":" & ST.wSecond           List1.AddItem path & FileName & vbTab & _              Format(DateCStr, "mm/dd/yyyy hh:nn:ss") _              & vbTab & Format(DateMStr, "mm/dd/yyyy hh:nn:ss")          End If         Cont = FindNextFile(hSearch, WFD)  ' Get next file      Wend      Cont = FindClose(hSearch)   End If   ' If there are sub-directories...    If nDir > 0 Then      ' Recursively walk into them...      For i = 0 To nDir - 1        FindFilesAPI = FindFilesAPI + FindFilesAPI(path & dirNames(i) _         & "\", SearchStr, FileCount, DirCount)      Next i   End If   End Function   Private Sub Command1_Click()   Dim SearchPath As String, FindStr As String   Dim FileSize As Long   Dim NumFiles As Integer, NumDirs As Integer   Screen.MousePointer = vbHourglass   List1.Clear   SearchPath = Text1.Text   FindStr = Text2.Text   FileSize = FindFilesAPI(SearchPath, FindStr, NumFiles, NumDirs)   Text3.Text = NumFiles & " Files found in " & NumDirs + 1 & _    " Directories"   Text4.Text = "Size of files found under " & SearchPath & " = " & _   Format(FileSize, "#,###,###,##0") & " Bytes"   Screen.MousePointer = vbDefault   End Sub					
  5. Run the Project. Enter a starting path into Text1, a search string in Text2 (like *.* or *.txt) and then click Command1.
You will see a list of the files found display in the ListBox with the create date and the last modified date, the actual number of files found displays in Text3, and the total size of the files found under the starting directory appears in Text4.

Method 2: Using Built-In Visual Basic Functions

These instructions build on the sample described prior, but can also beused in a new Project.
  1. Open the Project by using the steps described in Method1
  2. Add another CommandButton named Command2, two more TextBoxes named Text5 and Text6 and another ListBox, List2, to Form1.
  3. Copy the following code into Form1's module:
       Function FindFiles(path As String, SearchStr As String, _       FileCount As Integer, DirCount As Integer)      Dim FileName As String   ' Walking filename variable.      Dim DirName As String    ' SubDirectory Name.      Dim dirNames() As String ' Buffer for directory name entries.      Dim nDir As Integer      ' Number of directories in this path.      Dim i As Integer         ' For-loop counter.      On Error GoTo sysFileERR      If Right(path, 1) <> "\" Then path = path & "\"      ' Search for subdirectories.      nDir = 0      ReDim dirNames(nDir)      DirName = Dir(path, vbDirectory Or vbHidden Or vbArchive Or vbReadOnly _Or vbSystem)  ' Even if hidden, and so on.      Do While Len(DirName) > 0         ' Ignore the current and encompassing directories.         If (DirName <> ".") And (DirName <> "..") Then            ' Check for directory with bitwise comparison.            If GetAttr(path & DirName) And vbDirectory Then               dirNames(nDir) = DirName               DirCount = DirCount + 1               nDir = nDir + 1               ReDim Preserve dirNames(nDir)               'List2.AddItem path & DirName ' Uncomment to list            End If                           ' directories.   sysFileERRCont:         End If         DirName = Dir()  ' Get next subdirectory.      Loop      ' Search through this directory and sum file sizes.      FileName = Dir(path & SearchStr, vbNormal Or vbHidden Or vbSystem _      Or vbReadOnly Or vbArchive)      While Len(FileName) <> 0         FindFiles = FindFiles + FileLen(path & FileName)         FileCount = FileCount + 1         ' Load List box         List2.AddItem path & FileName & vbTab & _            FileDateTime(path & FileName)   ' Include Modified Date         FileName = Dir()  ' Get next file.      Wend      ' If there are sub-directories..      If nDir > 0 Then         ' Recursively walk into them         For i = 0 To nDir - 1           FindFiles = FindFiles + FindFiles(path & dirNames(i) & "\", _            SearchStr, FileCount, DirCount)         Next i      End If   AbortFunction:      Exit Function   sysFileERR:      If Right(DirName, 4) = ".sys" Then        Resume sysFileERRCont ' Known issue with pagefile.sys      Else        MsgBox "Error: " & Err.Number & " - " & Err.Description, , _         "Unexpected Error"        Resume AbortFunction      End If      End Function      Private Sub Command2_Click()      Dim SearchPath As String, FindStr As String      Dim FileSize As Long      Dim NumFiles As Integer, NumDirs As Integer      Screen.MousePointer = vbHourglass      List2.Clear      SearchPath = Text1.Text      FindStr = Text2.Text      FileSize = FindFiles(SearchPath, FindStr, NumFiles, NumDirs)      Text5.Text = NumFiles & " Files found in " & NumDirs + 1 & _       " Directories"      Text6.Text = "Size of files found under " & SearchPath & " = " & _      Format(FileSize, "#,###,###,##0") & " Bytes"      Screen.MousePointer = vbDefault      End Sub   Private Sub Form_Load()      Command1.Caption = "Use API code"      Command2.Caption = "Use VB code"      ' start with some reasonable defaults      Text1.Text = "C:\My Documents\"      Text2.Text = "*.*"   End Sub					
  4. Run the Project. Enter a starting path into Text1, a search string in Text2 (like *.* or Myfile?.txt, and so forth) and then click Command2.
You see a list of the files found appear in List2 with the last modified date, the number of files found in Text5, and the total size of the files found under the starting directory in Text6. By combining these two methods on one form you can verify that both methods return matching information.

Method 3: Use the FileSystem Object with Visual Basic

For information about using the FileSystemObject with Visual Basic tofind or list files, please see the following article in the MicrosoftKnowledge Base:
185601 How To Recursively Search Directories Using FileSystemObject
Properties

Article ID: 185476 - Last Review: 08/31/2009 12:55:40 - Revision: 4.0

  • Microsoft Visual Basic 5.0 Learning Edition
  • Microsoft Visual Basic 6.0 Learning Edition
  • Microsoft Visual Basic 5.0 Professional Edition
  • Microsoft Visual Basic 6.0 Professional Edition
  • Microsoft Visual Basic 5.0 Enterprise Edition
  • Microsoft Visual Basic Enterprise Edition for Windows 6.0
  • Microsoft Visual Basic 4.0 Standard Edition
  • Microsoft Visual Basic 4.0 Professional Edition
  • Microsoft Visual Basic 4.0 32-Bit Enterprise Edition
  • kbapi kbhowto KB185476
Feedback