_FileListToRekursiv Update: 08.07.2011

  • Hi!

    sc4ry
    Ich will das irgendwie hinbekommen, das die Func schneller wird!
    Leider habe ich keine Idee mehr !
    Aber mal sehen was noch geht! ^^


    @ syne
    Wow richtig dicken Rechner hast du da! :D


    LG Kleiner

  • Postet eure Testläufe!

    Hab mal das ganze gegen 6 andere Funktionen antreten lassen welche alle auf sehr verschiedenen Ansätzen und Lösungswegen basíeren.
    Testordner war eine Partition mit 178.994 Dateien und Ordner.
    Hier das Ergebnis (Skripte im Anhang):

    Testergebnisse

    -------------------- FLwStr ---------------------
    Dauer: 6023 ms
    -------------------------------------------------

    -------------------- FLwStrRek ---------------------
    Dauer: 5995 ms
    -------------------------------------------------

    -------------------- _FileListToArrayEx ---------------------
    Dauer: 6663 ms
    -------------------------------------------------

    -------------------- FileListCmd ---------------------
    Dauer: 7101 ms
    -------------------------------------------------

    -------------------- _FL2Arr ---------------------
    Dauer: 11521 ms
    -------------------------------------------------

    -------------------- _File_List_Rekursiv ---------------------
    Dauer: 8549 ms
    -------------------------------------------------

    -------------------- _GetFilesFolder_Rekursiv ---------------------
    Dauer: 86502 ms
    -------------------------------------------------


    Leider habe ich es nicht hinbekommen/verstanden wie du dir das vorstellst wenn man die Funktion mehrmals aufrufen will.
    Da du hier mit globalen Variablen arbeitest wird das vorherige Ergebnis einfach an das alte drangehangen und trotz aller Versuche mit dem Parameter $_Set_Runde_ konnte ich in einem weiteren Durchlauf nie wieder saubere Ergebnisse bekommen.
    Vielleicht könntest du da mal ein Beispiel machen wie es aussehen muss wenn ein Ordner mehrfach gelesen werden soll.
    Eine andere Frage: Hat es irgendeinen besonderen Grund warum du Zahlenwerte konsequent als 8-stellige Hex-Zahlen einträgst?

  • Ich habe gerade auch eine Funktion in meiner Sammlng entdeckt:

    Spoiler anzeigen
    [autoit]

    Global Enum Step *2 $FILELIST_FOLDERS=1, $FILELIST_FILES, $FILELIST_RECURSIVE
    ; #FUNCTION# ====================================================================================================================
    ; Name...........: _FileListToArrayEx
    ; Description ...: Recursive Filelist with Regex-comparison
    ; Syntax.........: _FileListToArrayEx($sPath, [$iMode=0, [Const $sRegExFiles='', [Const $sRegExFolders='']]])
    ; Parameters ....: $sPath - initial directory to search
    ; $iMode - listmode: Can be a BitOr-combination of the following values (default: all)
    ; |$FILELIST_FILES - list files
    ; |$FILELIST_FOLDERS - list folders
    ; |$FILELIST_RECURSIVE - include subdirectories in search
    ; $sRegExFiles - [Optional] RegEx to select files (searches only filename and extension, not whole path)
    ; $sRegExFolders - [Optional] RegEx to select folders (searches only current foldername, not whole path)
    ; $iMaxDepth - [Optional] maximum depth to list (default: -1=infinite)
    ; Return values .: Success - Array with the paths of the found files and folders, Array[0] contains the count.
    ; Failure - 0, @error set to:
    ; | 1 - could not search, possibly invalid initial directory
    ; | 2 - could not find any files
    ; Author ........: Prog@ndy
    ; Modified.......:
    ; Remarks .......:
    ; Related .......:
    ; Link ..........;
    ; Example .......;
    ; ===============================================================================================================================
    Func _FileListToArrayEx($sPath, $iMode=0, Const $sRegExFiles='', Const $sRegExFolders='', $iMaxDepth=-1)
    ; Author: Prog@ndy
    Local Static $files, $depth=0, $fRecurse, $fDirs, $fFiles
    If StringRight($sPath,1)<>'\' Then $sPath &= '\'
    Local $hFind = FileFindFirstFile($sPath & '*.*'), $sFile
    If @error=-1 Then Return SetError(1,0,0)

    [/autoit] [autoit][/autoit] [autoit]

    Switch $depth
    Case 0
    $files=''
    $fFiles = BitAND($iMode, $FILELIST_FILES)=$FILELIST_FILES Or $iMode=0
    $fDirs = BitAND($iMode, $FILELIST_FOLDERS)=$FILELIST_FOLDERS Or $iMode=0
    $fRecurse = BitAND($iMode, $FILELIST_RECURSIVE)=$FILELIST_RECURSIVE Or $iMode=0
    Case $iMaxDepth+1
    Return ; max depth reached, do not search further
    EndSwitch

    [/autoit] [autoit][/autoit] [autoit]

    $depth += 1
    If Mod($depth, 10)=0 Then Sleep(0)
    While 1
    $sFile = FileFindNextFile($hFind)
    If @error Then ExitLoop
    Switch @extended
    Case 1
    If $sRegExFolders And Not StringRegExp($sFile,$sREgExFolders) Then ContinueLoop
    If $fDirs Then $files&=$sPath&$sFile&'\|'
    If $fRecurse And Not __FLTAEx_FileIsSymlink($sPath&$sFile) Then _FileListToArrayEx($sPath&$sFile, $iMode, $sRegExFiles, $sRegExFolders)
    Case Else
    If $fFiles And ($sRegExFiles='' Or StringRegExp($sFile,$sRegExFiles)) Then $files &= $sPath&$sFile&'|'
    EndSwitch
    WEnd
    FileClose($hFind)
    $depth -= 1
    If $depth=0 Then
    If $files='' Then Return SetError(2,0,0)
    Local $ret = StringSplit(StringTrimRight($files,1), '|')
    $files=''
    Return $ret
    EndIf
    EndFunc
    Func __FLTAEx_FileIsSymlink($sFile)
    ; Author: Prog@ndy
    Local Static $hKernel = DllOpen('kernel32.dll')
    Local $n = DllCall($hKernel, 'dword', 'GetFileAttributesW', 'wstr', $sFile)
    If @error Then Return SetError(1,@error,0)
    Return BitAND($n[0], 1024)=1024 ; FILE_ATTRIBUTE_REPARSE_POINT
    EndFunc

    [/autoit]
  • Bin auch mal wieder hir!

    AspirinJunkie
    Tatsächlich meine alte Func hat auf ein Bestehendes array abgezielt!
    Noch mal überarbeitet .

    Und das mit den 8-stellige Hex-Zahlen war ein test.

    PS: Wenn du progandy und meine func antreten llassen willst dann bitte auf gleicher bassis denn in unser Func ist noche ein zusatz, bei progandy ( __FLTAEx_FileIsSymlink) und bei mir ( _F_L_) das
    ist eine Func zum prüfen von Symlink die eine Schleife verursacht.

    Post#1

    LG Kleiner

  • PS: Wenn du progandy und meine func antreten llassen willst dann bitte auf gleicher bassis denn in unser Func ist noche ein zusatz, bei progandy ( __FLTAEx_FileIsSymlink) und bei mir ( _F_L_) das
    ist eine Func zum prüfen von Symlink die eine Schleife verursacht.


    Hab die REPARSE_POINT-Abfrage noch mit in meine Funktionen eingebaut und deine Funktion aktualisiert und das Ergebnis sieht nun so aus:

    Spoiler anzeigen
    [autoit]

    -------------------- _FL2Arr ---------------------
    Dauer: 15466 ms
    -------------------------------------------------

    [/autoit] [autoit][/autoit] [autoit]

    -------------------- _FileListToArrayEx ---------------------
    Dauer: 6744 ms
    -------------------------------------------------

    [/autoit] [autoit][/autoit] [autoit]

    -------------------- FLwStr ---------------------
    Dauer: 6697 ms
    -------------------------------------------------

    [/autoit] [autoit][/autoit] [autoit]

    -------------------- FLwStrRek ---------------------
    Dauer: 6857 ms
    -------------------------------------------------

    [/autoit] [autoit][/autoit] [autoit]

    -------------------- _File_List_Rekursiv ---------------------
    Dauer: 5665 ms
    -------------------------------------------------

    [/autoit] [autoit][/autoit] [autoit]

    -------------------- FileListCmd ---------------------
    Dauer: 7765 ms
    -------------------------------------------------

    [/autoit] [autoit][/autoit] [autoit]

    -------------------- _GetFilesFolder_Rekursiv ---------------------
    Dauer: 104729 ms
    -------------------------------------------------

    [/autoit]


    Die _File_List_Rekursiv ist nun natürlich die schnellste von allen da sie die Suche nach einer dynamischen Datenstruktur komplett ignoriert in dem dort einfach ein Array mit 10066329 Elementen im Arbeitsspeicher erstellt wird.
    Alle anderen Funktionen versuchen hingegen nur soviel Speicher zu belegen wie sie tatsächlich benötigen, sei es über ein String, eine Queue oder ein kontinuierliches ReDim des Arrays.
    Das kostet natürlich Zeit, ist aber sauberer.

  • Morgen!

    AspirinJunkie
    Dynamischen Datenstruktur ist schon wichtig habe meine Func mit String umgebaut.
    Mir kam es darauf an so schnell wie möglich zu werden was ich auch mit eurer hilfe geschaft habe.
    Die Funktion übertrift meine erwartungen ich habe mir nicht vorstellen könne das AutoIT so schnell sien kann.
    Wie du schon selber geschrieben hast so viele ansätze Ideen der umsetzung einfach schön zu sehen vieviel leute sich um das Rkursiv gedanken machen! :D
    Hat mir sehr viel spass gemacht wenn du oder jemand noch ideen hat dann immer her damit. ;)

    FileList_S_Rekursiv in Post#1


    LG Kleiner

  • Ist wirklich gut geworden. :thumbup:
    Wie wäre es noch mit mehreren Filtern gleichzeitig? Also z.B. .mp3 und .wma in einem Rutsch.
    Müsste durch eine Änderung um Zeile 68 eigentlich möglich sein.

    edit \ Die Funktion von Progandy (die ist wieder mal krass gut :thumbup: ) kann das ja schon.
    Bei der Variante von kleiner27 hab ichs jetzt auf die schnelle nicht hinbekommen, das Skript wirkt etwas wie nach dem Obfuskator :D

    Einmal editiert, zuletzt von nuts (20. April 2010 um 16:05)

  • Guten Morgen!

    nuts
    Super Idee
    Habe ich sofort umgesetzt schlüssel war

    [autoit]

    StringRegExp($_F_N_, StringReplace(StringReplace($_Wildc_, '*', ''), ',', '|'))

    [/autoit]



    Post#1 update

    LG Kleinr

  • Hat mir sehr viel spass gemacht wenn du oder jemand noch ideen hat dann immer her damit. ;)


    Hat definitiv Spaß gemacht aber weitere Ideen hab ich erstmal nicht mehr.
    Wir haben aber nun viele verschiedene Ansätze für Teilprobleme welche man sich nun selbst frei zusammenbauen kann:

    • Auslesen der Dateien:
      • FileFind...File
      • dir-Kommandozeilenbefehl
      • Shell-Objekt
    • Datenstruktur zum Aufbau der Dateiliste:
      • ausreichend groß vordimensioniertes Array
      • Array mit kontinuierlichem ReDim
      • String
      • .Net-Strukturen (Stack, Queue, ArrayList)
    • Vorgehensweise beim durchgehen der Unterordner:
      • rekursiv
      • iterativ mit .Net Strukturen als Zwischenspeicher für Unterordner
      • iterativ mit String als Zwischenspeicher für Unterordner


    Hinzu kommen dann noch diverse Anpassungen wie z.B. Filtermöglichkeiten.
    Interessant wird es erst dann wieder wenn andere Ansätze hinzukommen.
    Mir persönlich fällt erstmal keiner dazu ein aber vielleicht dir. :)