FindFile

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
mpz
Beiträge: 505
Registriert: 14.06.2005 15:53
Computerausstattung: Win 11 Pro, 48 GB Ram, Intel I7 CPU und RX4070 Grafikkarte, PB (4/5) 6.12LT
Wohnort: Berlin, Tempelhof

FindFile

Beitrag von mpz »

Hallo Leute,

habe das FindFile aus dem englischen Forum auf Purebasic 4.10 Beta 4 angepasst. Wenn ich Zeit habe erweitere ich es um "Wildcards"...

Gruß Michael

Code: Alles auswählen


;-TOP 
; Kommentar : Eine einzelne Datei wird gesucht
;
; Version   : v1.00 
; Author    : by blueznl 15/Nov/2003 and by DiGe 03/Feb/2005 
;             Anpassung an 4.10 beta4 by Michael Paulwitz
;              
; Datei     : Findfile.pb 
; Erstellt  : 9.11.2007 
; Sprache   : Purebasic 4.10 Beta 4 Windows
; *************************************************************************************** 



Procedure.s FindFile(Dir.s,file.s) 
   Protected ID.l, files.s 

   If Right(Dir, 1) <> "\" 
      Dir + "\" 
   EndIf 

   ID = ExamineDirectory(#PB_Any, Dir, "") 
   If ID 
      While NextDirectoryEntry(ID) 
         Select DirectoryEntryType(ID) 
            Case 0 
               Break 
            Case #PB_DirectoryEntry_File 
               If UCase(DirectoryEntryName(ID)) = UCase(file.s)
                  ProcedureReturn Dir + DirectoryEntryName(ID)
                  Break
               EndIf
            Case #PB_DirectoryEntry_Directory
               If DirectoryEntryName(ID) <> "." And DirectoryEntryName(ID) <> ".." 
                  files.s = FindFile(Dir + DirectoryEntryName(ID),file.s) 
                  If files.s
                    Break
                  EndIf  
               EndIf 
         EndSelect 
      Wend 
      FinishDirectory(ID)
   EndIf 
   ProcedureReturn files.s 
EndProcedure 

Dir.s = PathRequester("Pfad auswählen...", "C:\") 

If Dir
   Dateisuchen.s = "explorer.exe"
   Datei.s = FindFile(Dir,Dateisuchen)
   If Datei
      MessageRequester(Dir, "Die Datei <" + Datei + "> wurde gefunden")
   Else
      MessageRequester(Dir, "Die Datei <" + Dateisuchen + "> wurde nicht gefunden")
   EndIf 
EndIf
End

Working on :lol: - LibSGD - MP3D Engine - 8)
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

// Edit: Verweisen möchte ich auf Seite 2 dieses Threads - dort gibt es noch besere Prozeduren, die auch Callbacks und das Suchen mehrerer Dateien auf einmal unterstützen.



Hier habe ich deine Version sehr stark verbessert:

Code: Alles auswählen

; AND51
; Nov-2007
; For free use, credits appreciated

Procedure.s FindFile(file.s, directory.s, recursive=1)
	PathAddBackslash_(@directory)
	Protected result.s, dir=ExamineDirectory(#PB_Any, directory, file)
	If dir And NextDirectoryEntry(dir)
		result=directory+DirectoryEntryName(dir)
		FinishDirectory(dir)
	ElseIf recursive
		dir=ExamineDirectory(#PB_Any, directory, "")
		If dir
			While NextDirectoryEntry(dir) And Not result
				If DirectoryEntryType(dir) = #PB_DirectoryEntry_Directory And DirectoryEntryName(dir) <> "." And DirectoryEntryName(dir) <> ".."
					result=FindFile(file, directory+DirectoryEntryName(dir), 1)
				EndIf
			Wend
			FinishDirectory(dir)
		EndIf
	EndIf
	ProcedureReturn result
EndProcedure


Debug FindFile("hiberfil.sys", "C:", 1)
  • Edit: Code leicht nachgebessert
  • Case-In-Sensivity, groß-/kleinschreibung egal
  • Wildcards können hemmungslos benutzt werden
  • Rekursive suche kann per Flag an- oder abgeschaltet werden
  • Intelligente Suche: Erst wird die Datei im aktuellen Verzeichnis gesucht, bevor rekursiv die nächsten Ordner durchsucht werden, spart Zeit

Dein Code geht rekursiv sofort in einen Ordner rein, wenn er einen gefunden hat. Dies führt dazu, dass zum Beispiel erst "Dokumente und Einstellungen" durchsucht wird, wenn du nach der Datei "pagefile.sys" suchst, da ExamineDirectory() meistens die Dateien alphabetisch zurückgibt. Dies spart sehr viel Zeit.


Du hast übrigens ein Speicherleck in deinem Code:
mpz hat geschrieben:

Code: Alles auswählen

               If UCase(DirectoryEntryName(ID)) = UCase(file.s) 
                  ProcedureReturn Dir + DirectoryEntryName(ID) 
                  Break 
               EndIf 
Was nützt dir dein Break, wenn du es erst nach ProcedureReturn einsetzt? Und warum verlässt du an dieser Stelle sofort die Prozedur? SO kannst du das Verzeichnis zum Schluss nicht mehr mit FinishDirectory() freigeben ( -> Speicherleck)!
Zuletzt geändert von AND51 am 14.11.2007 22:27, insgesamt 2-mal geändert.
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

AND51 hat geschrieben:Hier habe ich deine Version sehr stark verbessert
[hust] das staubt heute mal wieder... ;-)

Grüße ... Kiffi
a²+b²=mc²
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Kiffi hat geschrieben:[hust] das staubt heute mal wieder... ;-)
Ja, ich weiß auch nicht, woher das kommt... Vielleicht liegts an der Brille, musst du deine Brille auch mal wieder reinigen? 8)
Aber mal im Ernst: Die Idee, das Pattern-Parameter bei ExamineDiretory() zu mussbrauchen ist doch raffiniert, oder?


// Edit:
Von meinem Code sollte das Sternchen bei ExamineDirectory() (3. Parameter) entfernt werden, da sonst "Purebasic.exe" gefunden wird, obwohl man vielleicht nur nach "basic.exe" sucht.
Trotzdem können weiterhin munter Wildcards benutzt werden.
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Teil 2: FindMultipleFiles() - Findet mehr als nur die 1. Datei

Code: Alles auswählen

; AND51
; Nov-2007
; For free use, credits appreciated

EnableExplicit

Procedure FindMultipleFiles(file.s, directory.s, ResultList.s(), recursive=1)
	PathAddBackslash_(@directory)
	Protected dir=ExamineDirectory(#PB_Any, directory, file)
	If dir
		While NextDirectoryEntry(dir)
			AddElement(ResultList())
				ResultList()=directory+DirectoryEntryName(dir)
		Wend
		FinishDirectory(dir)
	EndIf
	If recursive
		dir=ExamineDirectory(#PB_Any, directory, "")
		If dir
			While NextDirectoryEntry(dir)
				If DirectoryEntryType(dir) = #PB_DirectoryEntry_Directory And DirectoryEntryName(dir) <> "." And DirectoryEntryName(dir) <> ".."
					FindMultipleFiles(file, directory+DirectoryEntryName(dir), ResultList(), 1)
				EndIf
			Wend
			FinishDirectory(dir)
		EndIf
	EndIf
	ProcedureReturn CountList(ResultList())
EndProcedure

NewList suche.s()

Debug FindMultipleFIles("*.sys", "C:", suche(), 1)
ForEach suche()
	Debug suche()
Next
Kiffi, basierend auf den exzellenten Vorteilen meines ersten Codes (staubt's immernoch? :mrgreen: )
habe ich den Code erweitert. Er findet nun ALLE Dateien, die auf die angegeben Parametern basieren und speichert die Ergebnisse bequem in die LinkedList, die man übergibt.
Außerdem wird am Schluss noch die Anzahl gefundener Dateien zurückgegeben (ProcedureReturn).

Das Tolle: Bei mir ist der Code selbst mit Debugger so schnell, dass es höchstens 1-3 Sekunden dauert, bis er mein Laufwerk C: komplett/rekursiv nach allen SYS-Dateien durchsucht hat (Ein Kontrolldurchlauf mit allen HTM-Dateien war ebenfalls so schnell). Oder ist diese Schnelligkeit nur bei mir so?
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

AND51 hat geschrieben: Das Tolle: Bei mir ist der Code selbst mit Debugger so schnell, dass es höchstens 1-3 Sekunden dauert, bis er mein Laufwerk C: komplett/rekursiv nach allen SYS-Dateien durchsucht hat (Ein Kontrolldurchlauf mit allen HTM-Dateien war ebenfalls so schnell). Oder ist diese Schnelligkeit nur bei mir so?
Das währe wirklich aussergewöhnlich schnell, das muss ich mal bei mir ausprobieren.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Benutzeravatar
Bisonte
Beiträge: 2470
Registriert: 01.04.2007 20:18

Beitrag von Bisonte »

dass es höchstens 1-3 Sekunden dauert,
Wenn Du minuten drauss machst, kommen wir ins Geschäft (565 Files gefunden ;)

Ansonsten hätt ich die Platte auch gerne :D

*Sry for Spam
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Die Geschwindigkeit hängt mit der Laufzeitindizierung der Festplatte
zusammen.

Versucht mal folgendes:
PC neustarten und Code ausführen. -> Dauert lange.
Code direkt danach nochmal ausführen. -> Geht sehr schnell.
Grund: Alle Verzeichnisinhalte wurden von Windows zwischengespeichert,
damit es beim nächsten Mal eben schneller geht.
Benutzeravatar
Bisonte
Beiträge: 2470
Registriert: 01.04.2007 20:18

Beitrag von Bisonte »

jetzt wo du das erwähnst ... stimmt... weniger als 2 Sekunden ... alle achtung.

Hätt ich auch selbst drauf kommen können ;)
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

Jopp ist bei mir ungefähr gleich schnell wie die Windows-Suche.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Antworten