Help and Support

文書番号: 185476 - 最終更新日: 2006年8月14日 - リビジョン: 3.1

ディレクトリ内のファイルの検索またはファイル一覧の取得を行う方法

目次

すべて展開する | すべて折りたたむ

概要

ファイル検索では多くの場合、サブディレクトリを検索する必要があります。この資料では、ディレクトリを再帰的に検索し、ファイル情報を取得するための 2 つの方法について説明します。

詳細

Visual Basic では、ファイルおよびディレクトリの情報を取得するためのメソッドが用意されていますが、これらの処理は Windows API 関数を使用して実行することもできます。API を使用するよりも組み込みのメソッドを使用した方が早いですが、この 2 つの方法には若干の違いがあります。この資料では、ファイルおよびディレクトリの情報を取得するための 2 つの方法の両方を説明します。両方の方法をテストする場合は、検索の開始位置のパスと検索文字列に同じものを使用してください。同様の結果が得られます。

Visual Basic for Applications (VBA) に含まれている Application.FileSearch オブジェクトを使用して、ファイル検索およびファイル一覧の取得を行うことができます。Application.FileSearch オブジェクトは Visual Basic で直接使用することはできませんが、Microsoft Office 97 製品から使用することができます。詳細および事例については、オンライン ヘルプに記載されています。または、「サポート技術情報」 (Microsoft Knowledge Base) で FileSearch を検索してください。

以下の例には完全なエラー トラップは含まれていません。ただし、方法 2 は、VB の GetAttr() 関数が Windows NT 仮想メモリ ページング ファイルである Pagefile.sys でエラーになる特殊なケースに対応しています。また、この API 版ではデフォルトで、検索文字列に応じて、ディレクトリ名の一覧と数が出力されます。VB 版にはこの機能はありません。 この 2 つの方法の実行結果で異なる点は、VB コードではファイルの作成日が返されないことだけです。

方法 1 : Windows API を使用する

  1. Visual Basic で、新しい標準 EXE プロジェクトを開始します。デフォルトで Form1 が作成されます。
  2. Form1 に CommandButton コントロールを追加し、Command1 という名前を付けます。TextBox コントロールを 4 つ追加し、それぞれ、Text1、Text2、Text3、Text4 という名前を付け、さらに、ListBox コントロールを 1 つ追加します。
  3. [プロジェクト] メニューからモジュールを追加し、次のコードを挿入します。
       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. 次のコードをコピーして Form1 のモジュールに貼り付けます。
       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. プロジェクトを実行します。[Text1] ボックスに検索開始位置のパスを入力し、[Text2] ボックスに検索文字列 (*.* または *.txt など) を入力します。[Command1] をクリックします。
リスト ボックスに、検索されたファイルの一覧が作成日および最終更新日と共に表示され、[Text3] には実際に検索されたファイルの数、[Text4] には検索開始位置のディレクトリ以下で検索されたファイルの合計サイズが表示されます。

方法 2 : 組み込みの Visual Basic 関数を使用する

以下の手順では、上記で説明したサンプルを続けて使用していますが、新しいプロジェクトを作成してもかまいません。
  1. 方法 1 で作成したプロジェクトを開きます。
  2. Form1 にもう 1 つ CommandButton コントロールを追加して Command2 という名前を付けます。TextBox コントロールを 2 つ追加して Text5、Text6 という名前を付け、さらにもう 1 つ List2 という名前で ListBox コントロールを追加します。
  3. 以下のコードをコピーして Form1 のモジュールに貼り付けます。
       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. プロジェクトを実行します。[Text1] ボックスに検索開始位置のパスを入力し、[Text2] ボックスに検索文字列 (*.* や Myfile?.txt など) を 入力し、[Use VB code] をクリックします。
[List2] に、検索されたファイルの一覧が最終更新日と共に表示され、[Text5] には検索されたファイルの数、[Text6] には検索開始位置のディレクトリ以下で検索されたファイルの合計サイズが表示されます。1 つのフォーム上にこの 2 つの方法を実装することで、どちらの方法でも返される結果が一致することを確認できます。

方法 3 : Visual Basic で FileSystemObject を使用する

Visual Basic で FileSystemObject を使用してファイルの検索やファイル一覧の取得を行う方法の関連情報を参照するには、以下の「サポート技術情報」 (Microsoft Knowledge Base) をクリックしてください。
185601? (http://support.microsoft.com/kb/185601/ ) FileSystemObject を使用して再帰的にディレクトリ検索を行う方法

この資料は以下の製品について記述したものです。
  • 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 6.0 Enterprise Edition
  • 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
"Microsoft Knowledge Baseに含まれている情報は、いかなる保証もない現状ベースで提供されるものです。Microsoft Corporation及びその関連会社は、市場性および特定の目的への適合性を含めて、明示的にも黙示的にも、一切の保証をいたしません。さらに、Microsoft Corporation及びその関連会社は、本文書に含まれている情報の使用及び使用結果につき、正確性、真実性等、いかなる表明・保証も行ないません。Microsoft Corporation、その関連会社及びこれらの権限ある代理人による口頭または書面による一切の情報提供またはアドバイスは、保証を意味するものではなく、かつ上記免責条項の範囲を狭めるものではありません。Microsoft Corporation、その関連会社 及びこれらの者の供給者は、直接的、間接的、偶発的、結果的損害、逸失利益、懲罰的損害、または特別損害を含む全ての損害に対して、状況のいかんを問わず一切責任を負いません。(Microsoft Corporation、その関連会社 またはこれらの者の供給者がかかる損害の発生可能性を了知している場合を含みます。) 結果的損害または偶発的損害に対する責任の免除または制限を認めていない地域においては、上記制限が適用されない場合があります。なお、本文書においては、文書の体裁上の都合により製品名の表記において商標登録表示、その他の商標表示を省略している場合がありますので、予めご了解ください。"

サポート技術情報の翻訳