List Files Recursive mit Filter

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.
SMaag
Beiträge: 150
Registriert: 08.05.2022 12:58

Re: List Files Recursive mit Filter

Beitrag von SMaag »

@jacdelad
Danke, ich hab's mir nochmals angesehen. Ich hätte das jetzt für komplizierter gehalten ohne Rekursion. Geht tatsächlich mit 2 While Schleifen.
Ich kenn das seit je her als Rekursion und wäre gar nicht auf die Idee gekommen das anders zu machen. Man lernt einfach nie aus!
Benutzeravatar
jacdelad
Beiträge: 341
Registriert: 03.02.2021 13:39
Computerausstattung: Ryzen 5800X, 108TB Festplatte, 32GB RAM, Radeon 7770OC
Wohnort: Riesa
Kontaktdaten:

Re: List Files Recursive mit Filter

Beitrag von jacdelad »

Hier ein wenig optimiert und mit Maske. Da ich zu blöd bin die Dateimaske in RegEx zu übersetzen muss jedes Verzeichnis doppelt gescannt werden (einmal für die Unterordner und einmal für die Dateien mit Maske). Vielleicht weiß jemand, wie man die Dateimaske (z.B. "*.dll") in RegEx übersetzen kann, dann würde ein Durchlauf reichen.

Code: Alles auswählen

EnableExplicit

Procedure ListRecursive(Dir$,List Liste.s(),Maske$="*.*")
  Protected NewList DirList.s(),exa
  AddElement(DirList())
  DirList()=RTrim(Dir$,"\")
  Repeat
    FirstElement(DirList())
    Dir$=DirList()
    DeleteElement(DirList())
    exa=ExamineDirectory(#PB_Any,Dir$,"*.*")
    If exa
      While NextDirectoryEntry(exa)
        If DirectoryEntryType(exa)=#PB_DirectoryEntry_Directory
          If ReplaceString(DirectoryEntryName(exa),".","")<>""
            AddElement(DirList())
            DirList()=Dir$+"\"+DirectoryEntryName(exa)
          EndIf
        EndIf
      Wend
      FinishDirectory(exa)
    EndIf
    exa=ExamineDirectory(#PB_Any,Dir$,Maske$)
    If exa
      While NextDirectoryEntry(exa)
        If DirectoryEntryType(exa)=#PB_DirectoryEntry_File
          AddElement(Liste())
          Liste()=Dir$+"\"+DirectoryEntryName(exa)
          ;Attribute etc...
        EndIf
      Wend
    EndIf
  Until ListSize(DirList())=0
EndProcedure

Global NewList MyList.s()
OpenConsole()
ListRecursive("C:\Windows\System32",MyList(),"*.dll")
ForEach MyList()
  PrintN(MyList())
Next
PrintN("Fertig!")
Input()
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
SMaag
Beiträge: 150
Registriert: 08.05.2022 12:58

Re: List Files Recursive mit Filter

Beitrag von SMaag »

hab jetzt mal aus Neugier die beiden Versionen für Files auflisten
1x recursiv und 1x ohne Rekursion (mit 2 While Schleifen) in der Grundausführung (also ohne Filter usw.)
gegeneinader getestet.
Auf meinem Rechner dauert eine komplette Auflistung eines relativ großen Verzeichnisbaums damit knapp 2sec (ab dem 2ten Anlauf, wenn alles im Cache ist). Die rekursive Version ist etwas langsamer (rund 7%). Meine aufwendige Version mit den ganzen Filtermöglichkeiten ist deutlich abgeschlagen.
Benutzeravatar
jacdelad
Beiträge: 341
Registriert: 03.02.2021 13:39
Computerausstattung: Ryzen 5800X, 108TB Festplatte, 32GB RAM, Radeon 7770OC
Wohnort: Riesa
Kontaktdaten:

Re: List Files Recursive mit Filter

Beitrag von jacdelad »

Ja, die Filter brauchen natürlich ihre Zeit (und Dinge wie Attribute ermitteln und so auch). Geschwindigkeitstests immer mit ausgeschaltetem Debugger machen, das Ergebnis kann erheblich anders aussehen!
Letztendlich kann der eine Algorithmus den anderen überholen, wenn man Netzwerkordner scannt oder besonders viele Dateien oder Ordner drin sind oder der Datenträger besonders schnell/langsam ist oder...
Ich bevorzuge weiterhin den nichtrekursiven Algorithmus, aber im Endeffekt ist das Ergebnis das, was zählt. Wenn ich alle Dateien suche kann ich das schnell in einem Durchlauf machen, wenn ich Dateifilter benötige, dann muss ich zwei machen (solange ich das nicht mir RegEx hinkriege). Hat halt alles Vor- und Nachteile und sollte immer an den Zweck angepasst sein.
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
fabulouspaul
Beiträge: 120
Registriert: 01.04.2011 21:59

Re: List Files Recursive mit Filter

Beitrag von fabulouspaul »

Das mit dem Wildcard-Ersatz als RegEx sollte nicht so schwierig sein.
Im Dateisystem steht '?' für genau ein beliebiges Zeichen, das ist bei einer RegEx ein '.'
Im Dateisystem steht '*' für beliebig viele beliebige Zeichen, das ist bei einer RegEx '.*'
Bleibt nur noch der echte Punkt im Dateisystem, den man in der RegEx mit '\.' abbilden müsste

Aus '*.dll' als Maske im Dateisystem wird also die RegEx '.*\.dll'

Achtung ist ungetestet, sollte aber funktionieren.
Benutzeravatar
jacdelad
Beiträge: 341
Registriert: 03.02.2021 13:39
Computerausstattung: Ryzen 5800X, 108TB Festplatte, 32GB RAM, Radeon 7770OC
Wohnort: Riesa
Kontaktdaten:

Re: List Files Recursive mit Filter

Beitrag von jacdelad »

...ist es eben nicht:

Code: Alles auswählen

EnableExplicit

Procedure ListRecursive(Dir$,List Liste.s(),Maske$="*.*")
  Protected NewList DirList.s(),exa,RegEx
  AddElement(DirList())
  DirList()=RTrim(Dir$,"\")
  Maske$=ReplaceString(Maske$,".","\.")
  Maske$=ReplaceString(Maske$,"$","\$")
  Maske$=ReplaceString(Maske$,"+","\+")
  Maske$=ReplaceString(Maske$,"(","\(")
  Maske$=ReplaceString(Maske$,")","\)")
  Maske$=ReplaceString(Maske$,"[","\[")
  Maske$=ReplaceString(Maske$,"]","\]")
  Maske$=ReplaceString(Maske$,"?",".")
  Maske$="^"+ReplaceString(Maske$,"*",".*")+"$"
  RegEx=CreateRegularExpression(#PB_Any,Maske$,#PB_RegularExpression_NoCase)
  Repeat
    FirstElement(DirList())
    Dir$=DirList()
    DeleteElement(DirList())
    exa=ExamineDirectory(#PB_Any,Dir$,"*.*")
    If exa
      While NextDirectoryEntry(exa)
        If DirectoryEntryType(exa)=#PB_DirectoryEntry_Directory
          If ReplaceString(DirectoryEntryName(exa),".","")<>""
            AddElement(DirList())
            DirList()=Dir$+"\"+DirectoryEntryName(exa)
          EndIf
        Else
          If MatchRegularExpression(RegEx,DirectoryEntryName(exa))
             AddElement(Liste())
             Liste()=Dir$+"\"+DirectoryEntryName(exa)
             ;Attribute etc...
          EndIf
        EndIf
      Wend
      FinishDirectory(exa)
    EndIf
  Until ListSize(DirList())=0
EndProcedure

Global NewList MyList.s()
OpenConsole()
ListRecursive("C:\Windows\System32",MyList(),"push*")
ForEach MyList()
  PrintN(MyList())
Next
PrintN("Fertig!")
Input()
...findet auch "pushobj.dll.mui". Wie gesagt, es gibt so viel zu beachten, dass ich das nicht weiter durchprobieren will. Allein schon die ganzen Ersatzzeichen einbauen...
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
Antworten