FileFindFirstFile(): Dateien auch in Unterverzeichnissen wiedergeben

  • Guten Morgen an alle,

    ich möchte es irgendwie mit den beiden Funktionen

    [autoit]

    FileFindFirstFile()
    FileFindNextFile()

    [/autoit]

    es schaffen, dass es mir auch die Dateien in den Unterverzeichnissen wiedergibt. Gibt es da eine Möglichkeit? Ich teste es gerade mit einer weiteren Funktion

    [autoit]

    FileGetAttrib()

    [/autoit]

    jedoch bin ich noch am überlegen, wie ich es umsetzen könnte. Oder kennt jemand eine andere Lösung? Wäre euch sehr Dankbar.

    MfG

    Mehmet T.

    Einmal editiert, zuletzt von MehmeX (16. April 2011 um 01:36)

    • Offizieller Beitrag

    Ein Ansatz wäre eine Funktion zu schreiben und wenn FileFindNextFile bei @extended ein TRUE liefert (Verzeichnis gefunden) rufst Du die Funktion erneut (rekursiv) auf.
    Bei meiner Funktion habe ich das so verwendet:

    Spoiler anzeigen
    [autoit]


    ;===============================================================================
    ; Function Name: _RecursiveFileListToArray($sPath[, $sPattern][, $iFlag][, $iFormat][, $fRecursion][, $sDelim])
    ; Description:: gibt Verzeichnisse (rekursiv) und/oder Dateien zurück, die einem RegExp-Pattern entsprechen
    ; Parameter(s): $sPath = Startverzeichnis
    ; $sPattern = ein beliebiges RexExp-Pattern für die Auswahl
    ; $iFlag = Auswahl
    ; 0 = Dateien & Verzeichnisse
    ; 1 = nur Dateien
    ; 2 = nur Verzeichnisse
    ; $iFormat = Rückgabeformat
    ; 0 = String
    ; 1 = Array mit [0] = Anzahl
    ; 2 = Nullbasiertes Array
    ; $fRecursion = Verzeichnisse rekursiv durchsuchen
    ; False = Nein
    ; True = Ja
    ; $sDelim = Trennzeichen für die String-Rückgabe
    ; Requirement(s): AutoIt 3.3.0.0
    ; Return Value(s): Array/String mit den gefundenen Dateien/Verzeichnissen
    ; Author(s): Oscar (http://www.autoit.de)
    ; Anregungen von: bernd670 (http://www.autoit.de)
    ; und: AspirinJunkie (http://www.autoit.de)
    ;===============================================================================
    Func _RecursiveFileListToArray($sPath, $sPattern = '', $iFlag = 0, $iFormat = 1, $fRecursion = True, $sDelim = @CRLF, $fOpenDLL = True)
    Local $hSearch, $sFile, $sReturn = '', $aD
    Local Static $hDll
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    $hSearch = FileFindFirstFile($sPath & '*')
    If @error Or $hSearch = -1 Then Return SetError(1, 0, $sReturn)
    If $fOpenDLL Then $hDll = DllOpen('kernel32.dll')
    While True
    $sFile = FileFindNextFile($hSearch)
    If @error Then ExitLoop
    If @extended Then
    $aD = DllCall($hDll, 'dword', 'GetFileAttributesW', 'wstr', $sPath & $sFile)
    If @error Or BitAND($aD[0], 0x400) Then ContinueLoop
    If StringRegExp($sPath & $sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 2) Then $sReturn &= $sPath & $sFile & '\' & $sDelim
    If $fRecursion Then $sReturn &= _RecursiveFileListToArray($sPath & $sFile & '\', $sPattern, $iFlag, 0, True, $sDelim, False)
    ContinueLoop
    EndIf
    If StringRegExp($sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 1) Then $sReturn &= $sPath & $sFile & $sDelim
    WEnd
    FileClose($hSearch)
    If $fOpenDLL Then DllClose($hDll)
    If $iFormat And $sReturn = '' Then Return StringSplit($sReturn, '', $iFormat)
    If $iFormat Then Return StringSplit(StringTrimRight($sReturn, StringLen($sDelim)), $sDelim, $iFormat)
    Return $sReturn
    EndFunc

    [/autoit]
  • Ich habe mal ein Script geschrieben, welches mir alle Dateien aus allen Unterordnern in einen anderen Ordner verschiebt, vielleicht hilft es dir weiter
    (bei mir sind maximal 3 Unterordner, aber wenn du _FileListToArray nur nach Ordner suchen lässt, lässt es sich variabler machen)

    [autoit]

    $File = FileSelectFolder("Ordner auswählen", "C:\", 3)
    If @error Then Return SetError( 3, 0, 0)
    $Rangeordner = _FileListToArray($File &"\", "*", 2)
    If Not IsArray($Rangeordner) Then Return SetError(1, 0, 0)
    For $i = 1 To $Rangeordner[0]
    $RangeinOrdner = _FileListToArray($File &"\"&$Rangeordner[$i], "*", 2)
    IF Not IsArray($RangeinOrdner) Then Return SetError(2, 0, 0)
    For $k = 1 To $RangeinOrdner[0]
    $Rangefiles = _FileListToArray($File &"\"&$Rangeordner[$i]&"\"&$RangeinOrdner[$k], "*.mp3", 1)
    If Not @error Then
    For $s = 1 To $Rangefiles[0]
    FileMove($File &"\"&$Rangeordner[$i]&"\"&$RangeinOrdner[$k]&"\"&$Rangefiles[$s], $File &"\"&$Rangefiles[$s], 8)
    Next
    EndIf
    Next
    Next
    EndFunc

    [/autoit]
  • Danke erstmals für eure Antworten, das hat mir schon einmal weitergeholfen. Was ich bemerkt habe ist, dass die Funktion FileFind...() die Verzeichnisse immer am schluss wiedergeben, oder?

    EDIT: SUPER, ich habe eine Funktion, mit den Tipps von Oscar , geschrieben und es funktioniert. Hier der Code:

    Spoiler anzeigen
    [autoit]

    $SelectPfad = @ScriptDir & "\Test"
    _FileFind($SelectPfad)

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

    Func _FileFind($Pfad)
    $FindFile = FileFindFirstFile($Pfad & "\*.*")

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

    While 1
    $NextFile = FileFindNextFile($FindFile)
    If @error Then Exit
    If @extended Then
    $NewPfad = $Pfad & "\" & $NextFile
    _FileFind($NewPfad)
    EndIf

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

    MsgBox(64, "Test", "Name: " & $NextFile)
    WEnd
    EndFunc

    [/autoit]

    3 Mal editiert, zuletzt von MehmeX (14. April 2011 um 14:08)

  • Also ich habe es wieder min. 5x getestet und er gibt mir das Verzeichnis immer zuletzt zurück.

  • Führe mal folgendes Skirpt aus:

    Spoiler anzeigen
    [autoit]

    $FFFF = FileFindFirstFile(@SystemDir & '\*')
    If @error Then Exit

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

    Do
    $sFile = FileFindNextFile($FFFF)
    If @error Then ExitLoop
    ConsoleWrite(@extended)
    Until 0
    ConsoleWrite(@CRLF)

    [/autoit]


    Wenn es so wäre wie du beschreibst würde in der Scite4AutoIt-Konsole erstmal nur die Nullen stehen und ganz am Ende nur ganz allein die Einsen.
    Bei mir ist das aber, wie gesagt, nicht der Fall sondern wild durcheinander.
    Die Reihenfolge von FileFindNextFile ist nicht davon abhängig ob es ein Ordner oder eine Datei ist sondern alphabetisch sortiert.

  • Aja, ok Danke für deine Antwort.

    Das Blöde daran ist jetzt, wenn ein Verzeichnis vor Ende der Wiedergabe, der Dateien im aktuellen Verzeichnis, erscheint, dann werden die Dateien die nach dem Verzeichnis wieder gegeben werden würden, einfach ausgelassen.

  • wenn du alle Dateien und Ordner haben willst,
    würd ich dir _FileListToArray empfehlen, da kannst du nach Ordnern und nach Dateien getrennt suchen, und dann in den nächsten Ordner gehen und das selbe da wieder

  • Ich habe mal eine Funktion mit _FileListToArray() geschrieben, hier der Code:

    Spoiler anzeigen
    [autoit]

    #include <File.au3>
    #include <Array.au3>

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

    $Pfad = @ScriptDir
    $FileListFile = _FileListToArray($Pfad, "*", 1)
    $FileListFolder = _FileListToArray($Pfad, "*", 2)

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

    While 1
    For $flf = 1 To $FileListFile[0]
    _ArrayDisplay($FileListFile)
    ExitLoop
    Next

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

    $FileListFolder = _FileListToArray($Pfad, "*", 2)

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

    For $flfolder = 1 To $FileListFolder[0]
    $FileListFile = _FileListToArray($Pfad & "\" & $FileListFolder[$flfolder], "*", 1)
    If @error Then MsgBox(16, "Fehler", @error)
    $Pfad = $Pfad & "\" & $FileListFolder[$flfolder]
    Next
    WEnd

    [/autoit]

    Nur das Problem an der Funktion ist, dass sobald ein zweiter oder dritter Ordner sich darin befindet, dann klappt es mit der Pfadzuweisung nicht.

    Einmal editiert, zuletzt von MehmeX (14. April 2011 um 17:25)

  • Spoiler anzeigen
    [autoit]

    #include <File.au3>
    #include <Array.au3>
    $Timer = TimerInit()
    $Pfad = "C:\"
    Dim $Alldat[500000][2]
    Dim $Alldir[1]
    _ArrayAdd($Alldir, "")
    $Ordner = _FileListToArray($Pfad, "*", 2)
    If IsArray($Ordner) Then
    For $i = 1 To $Ordner[0]
    _ArrayAdd($Alldir, "\" & $Ordner[$i])
    $SubOrdner = _FileListToArray($Pfad & "\" & $Ordner[$i], "*", 2)
    If Not IsArray($SubOrdner) Then ContinueLoop
    For $j = 1 To $SubOrdner[0]
    _ArrayAdd($Alldir, "\" & $Ordner[$i] & "\" & $SubOrdner[$j])
    $SubSubOrdner = _FileListToArray($Pfad & "\" & $Ordner[$i] & "\" & $SubOrdner[$j], "*", 2)
    If Not IsArray($SubSubOrdner) Then ContinueLoop
    For $k = 1 To $SubSubOrdner[0]
    _ArrayAdd($Alldir, "\" & $Ordner[$i] & "\" & $SubOrdner[$j] & "\" & $SubSubOrdner[$k])
    $SubSubSubOrdner = _FileListToArray($Pfad & "\" & $Ordner[$i] & "\" & $SubOrdner[$j] & "\" & $SubSubOrdner[$k], "*", 2)
    If Not IsArray($SubSubSubOrdner) Then ContinueLoop
    For $l = 1 To $SubSubSubOrdner[0]
    _ArrayAdd($Alldir, "\" & $Ordner[$i] & "\" & $SubOrdner[$j] & "\" & $SubSubOrdner[$k] & "\" & $SubSubSubOrdner[$l])
    ;~ $SubSubSubSubOrdner = _FileListToArray($Pfad & "\" & $Ordner[$i] & "\" & $SubOrdner[$j] & "\" & $SubSubOrdner[$j] & "\" & $SubSubSubOrdner[$l], "*", 2)
    Next
    Next
    Next
    Next
    EndIf
    $Alldir[0] = UBound($Alldir) - 1
    ;~ _ArrayDisplay($Alldir)
    $row = 0
    For $i = 1 To $Alldir[0]
    $Dats = _FileListToArray($Pfad & $Alldir[$i], "*", 1)
    If Not IsArray($Dats) Then ContinueLoop
    For $k = 1 To $Dats[0]
    $row += 1
    $Alldat[$row][0] = $Dats[$k]
    $Alldat[$row][1] = FileGetAttrib($Pfad & $Alldir[$i] &"\"&$Dats[$k])
    Next
    Next
    ReDim $Alldat[$row + 1][2]
    $Alldat[0][0] = UBound($Alldat) - 1
    $Diff = TimerDiff($Timer)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $Diff = ' & $Diff / 1000 & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    _ArrayDisplay($Alldat)

    [/autoit]

    Das Scipt durchsucht alle Ordner + Unterordner ( bis jetzt 3 stufig, aber denke es ist gut sichtbar, wie es erweiterbar ist)
    Am ENde kommt ein Array raus mit den Dateinamen und den Status aus FileGetAttrib
    Gedauert hat es bei mir mit ca. 350 Ordnern und 26000 Dateien 4,5 Sek, also geschwindigkeitmäßig ist auch alles im grünen bereich ;)