Kontakt
DSVGO
Historie | |
26.06.2001 | Bestimmung des langen Dateinamens |
20.12.2000 | Erste Version: (rekursive) Durchsuchung eines Verzeichnisses |
Im folgenden werden die Find*File-API-Routinen verwendet, um eine Liste aller Dateien gemäß einem Pattern zu suchen (FindFiles) bzw. den langen (Win32-)Dateinamen aus einem kurzen (DOS-)Pfad zu bestimmen (LongFilename).
Mit der unten stehenden Funktion FindFiles ist es möglich, einen Dateibaum gemäß eines Datei-Patterns (z.B. "*.txt") zu durchsuchen. Optional können erforderliche Datei-Attribute (s.a. GetAttr in der VB-Hilfe) angegeben werden. Mit dem Recursive-Parameter kann definiert werden, ob alle Unter-Verzeichnisse ebenfalls durchsucht werden sollen (Voreinstellung), oder nicht. Zurückgegeben wird die Anzahl der gefundenen Dateien.
Der Parameter Files enthält nach Funktions-Ausführung eine Collection aller gefundenen Dateien (mitsamt vollständigem Pfad). Die Funktion kann auch mehrmals hintereinander (mit unterschiedlichen Such-Parametern) aufgerufen werden; Dann werden alle neu gefundenen Dateien der Collection hinzugefügt.
Übrigens: Soll nur nach genau einer bestimmten Datei sehr schnell gesucht werden, genügt ein deutlich geringerer Aufwand (siehe FindFile).
Im folgenden Beispiel werden alle HTML-Dateien im Verzeichnis "D:\Tmp" angezeigt, welche mit "j" anfangen und das Archiv-Bit gesetzt haben. Man beachte, wie die beiden üblichen Datei-Endungen einfach durch "Hintereinander-Schaltung" berücksichtigt werden:
Dim Dateien As Collection Dim i As Long If FindFiles("D:\Tmp", Dateien, "j*.htm", vbArchive) _ + FindFiles("D:\Tmp", Dateien, "j*.html", vbArchive) _ Then For i = 1 To Dateien.Count MsgBox Dateien(i) Next i Else MsgBox "Nichts gefunden!" End If
Alternativ kann auch folgende Variante genutzt werden:
Dim Dateien As Collection Dim i As Long FindFiles "D:\Tmp", Dateien, "j*.htm", vbArchive FindFiles "D:\Tmp", Dateien, "j*.html", vbArchive If Dateien.Count Then For i = 1 To Dateien.Count MsgBox Dateien(i) Next i Else MsgBox "Nichts gefunden!" End If
Folgende API-Funktionen und -Deklarationen werden benötigt (müssem im Deklarationsteil des Moduls stehen):
Private Declare Sub FindClose Lib "kernel32" ( _ ByVal hFindFile As Long) Private Declare Function FindFirstFileA Lib "kernel32" ( _ ByVal lpFileName As String, _ lpFindFileData As WIN32_FIND_DATA _ ) As Long Private Declare Function FindNextFileA Lib "kernel32" ( _ ByVal hFindFile As Long, _ lpFindFileData As WIN32_FIND_DATA _ ) As Long Private Declare Function GetFileAttributesA Lib "kernel32" ( _ ByVal lpFileName As String _ ) As Long 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 * 260 cAlternate As String * 14 End Type
Hier nun die eigentliche Funktion:
Public Function FindFiles( _ ByVal Path As String, _ ByRef Files As Collection, _ Optional ByVal Pattern As String = "*.*", _ Optional ByVal Attributes As VbFileAttribute = vbNormal, _ Optional ByVal Recursive As Boolean = True _ ) As Long Const vbErr_PathNotFound = 76 Const INVALID_VALUE = -1 Dim FileAttr As Long Dim FileName As String Dim hFind As Long Dim WFD As WIN32_FIND_DATA 'Initialisierung: If Right$(Path, 1) <> "\" Then _ Path = Path & "\" If Files Is Nothing Then _ Set Files = New Collection Pattern = LCase$(Pattern) 'Suche starten: hFind = FindFirstFileA(Path & "*", WFD) If hFind = INVALID_VALUE Then _ Err.Raise vbErr_PathNotFound 'Suche fortsetzen: Do FileName = LeftB$(WFD.cFileName, _ InStrB(WFD.cFileName, vbNullChar)) FileAttr = GetFileAttributesA(Path & FileName) If FileAttr And vbDirectory Then 'Verzeichnis analysieren: If Recursive Then If FileAttr <> INVALID_VALUE _ And FileName <> "." And FileName <> ".." _ Then FindFiles = FindFiles + FindFiles( _ Path & FileName, Files, Pattern, Attributes) End If End If Else 'Datei analysieren: If (FileAttr And Attributes) = Attributes Then If LCase$(FileName) Like Pattern Then FindFiles = FindFiles + 1 Files.Add Path & FileName End If End If End If Loop While FindNextFileA(hFind, WFD) FindClose hFind End Function
Ein neben-Effekt der oben gezeigten Routine ist die Füllung der WIN32_FIND_DATA-Struktur mit dem langen (unter Win32 üblichen) Dateinamen, auch wenn die Suche mit einem kurzen (DOS-kompatiblen, also 8+3 Zeichen langen) Namen durchgeführt wurde. Auf das Notwendigste reduziert, ergibt sich folgender Code:
Public Function LongFilename( _ ByRef FilePath As String) As String Const INVALID_VALUE = -1 Dim hFind As Long Dim WFD As WIN32_FIND_DATA hFind = FindFirstFileA(FilePath, WFD) If hFind <> INVALID_VALUE Then LongFilename = LeftB$(WFD.cFileName, _ InStrB(WFD.cFileName, vbNullChar)) FindClose hFind End If End Function
Eine Datei "D:\Test\Langer Name.txt" hat i.A. den Kurznamen "Langer~1.txt", also gibt LongFilename gerade den String "Langer Name.txt" zurück.
Übrigens: In "Lange Pfade in (kurze) DOS-Pfade" ist die Umkehrfunktion zu finden.
© Jost Schwider, 20.12.2000-26.06.2001 - http://vb-tec.de/fndfiles.htm