Rekursive File/Dateisuche mit Filter setzen

  • Hallo zusammen,
    ich drehe mich (mal wieder) im Kreis und finde keine Erklärung zu meinem Effekt/Fehler. Daher wende ich mich hier ans Forum und hoffe auf einen Tip oder gar eine Lösung.

    Beschreibung / Ziel des Ganzen:
    - Rekursiver Vergleich/Suche von Files über zwei beliebig zu wählende Startpunkte
    Tools:
    - UDF - _RecursiveFileListToArray()
    Ablauf (schematisch):
    - Start des Scripts – öffnet GUI zur Auswahl der StartVerzeichnisse und ggf. Filter
    - Suche läuft
    - Ergebnisanzeige mittels _ArrayDispaly()
    Ergebnis:
    Die Differenz der gefundenen Dateien (je nach gesetztem Filter).
    Im Ergebnis Array wird in einer Spalte der Name der Datei aufgeführt und in einer zweiten Spalte in welchem Verzeichnis sich das File befindet

    Problem:
    wie oben beschrieben funktioniert das auch soweit. Die Suche funktioniert mit allen möglichen Filtern (von *.*, über eigene nicht in der Listbox aufgeführte Filter).
    Das Problem taucht nur beim Einsatz genau eines Filters auf – dem für die Excel Files auf (der Letzte der Liste) - WARUM - ich sehe bzw. verstehe es nicht !
    Die Filter (RegEx Format) sehen wie folgt aus:
    .+\.(txt|TXT) - OK
    .+\.(doc|DOC|docx|DOCX) ) - OK
    .+\.(nsf|NSF|ntf|NTF) ) - OK
    .+\.(xls|XLS|xlsx|XLSX|xlsm|XLSM) - FEHLERHAFTER FILTER !

    Fehler:
    (Der Abbruch wird im Script an folgender Stelle erzeugt (Zeile 124))
    ..\cde_file_search_compare_testGUI.au3 (124) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:
    $aResult[$iNew][0] = $aReturn2[$i] ^ ERROR ->11:19:38 AutoIT3.exe ended.rc:1

    ScriptSnip Fehlerstelle:
    ;~ _ArrayDisplay($aResult)
    For $i = 1 To $aReturn2[0]
    $aResult[$iNew][0] = $aReturn2[$i]
    $aResult[$iNew][3] = "nur auf '" & $cde_Verz2 & "' vorhanden" ;Kenzeichnung dass Datei nur in 2
    $iNew += 1
    Next
    $aResult[0][0] = $iNew - 1
    ReDim $aResult[$iNew][4]
    $aResult[0][1] = $cde_Verz1
    $aResult[0][2] = $cde_Verz2
    $aResult[0][3] = "Differenz"
    Return $aResult
    EndFunc ;==>_Check
    (Anm.: Natürlich sind in den Testverzeichnissen entsprechende Files (in beliebiger Kombination) vorgehalten.)

    Script:

    [autoit]


    #include <Array.au3>
    #include <ButtonConstants.au3>
    #include <Date.au3>
    #include <EditConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>

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

    Opt("GUIDataSeparatorChar", "¦")

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

    $pattern1 = "*.txt"
    $pattern2 = "*.doc | docx"
    $pattern3 = "*.nsf | ntf"
    $pattern4 = "*.xls | xlsx | xlsm"

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

    ;~ '.+\.(txt|TXT)'
    ;~ '.+\.(doc|DOC|docx|DOCX)'
    ;~ '.+\.(xls|XLS|xlsx|XLSX|xlsm|XLSM)'
    ;~ '.+\.(nsf|NSF|ntf|NTF)'

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

    $Form1 = GUICreate("DirSync / Compare", 317, 232, 471, 156)
    $LabelVZ1 = GUICtrlCreateLabel("Set Directory 1: ", 24, 48, 93, 20)
    GUICtrlSetFont(-1, 9, 800, 0, "Century Gothic")
    $LabelVz2 = GUICtrlCreateLabel("Set Directory 2: ", 24, 80, 93, 20)
    GUICtrlSetFont(-1, 9, 800, 0, "Century Gothic")
    $InputVz1 = GUICtrlCreateInput("d:\test1", 120, 48, 153, 21)
    $InputVz2 = GUICtrlCreateInput("d:\test2", 120, 80, 153, 21)
    ;~ $InputPattern = GUICtrlCreateInput("*.*", 120, 120, 153, 21)
    $LabelFilter = GUICtrlCreateLabel("Set Filter:", 43, 126, 54, 20)
    GUICtrlSetFont(-1, 9, 800, 0, "Century Gothic")

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

    $FilterCombo = GUICtrlCreateCombo("*.*", 120, 120, 153, 21)
    GUICtrlSetFont(-1, 9, 400, 0, "Century Gothic")
    GUICtrlSetData(-1, $pattern1 & '¦' & $pattern2 & '¦' & $pattern3 & '¦' & $pattern4) ; add other item and set a new default
    GUICtrlSetFont(-1, 8, 800, 0, "Century Gothic")

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

    $GroupEingaben1 = GUICtrlCreateGroup(" Recursive Search - Parameter ", 8, 16, 289, 193)
    GUICtrlSetFont(-1, 10, 800, 0, "MS Sans Serif")
    $Button1OK = GUICtrlCreateButton("Start", 40, 168, 97, 25)
    $Button2Cancel = GUICtrlCreateButton("Cancel", 176, 168, 97, 25)
    GUICtrlCreateGroup("", -99, -99, 1, 1)
    GUISetState(@SW_SHOW)

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

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $Button1OK
    $cde_Verz1 = (GUIctrlread($InputVz1))
    $cde_Verz2 = (GUIctrlread($InputVz2))
    $cde_FileExt = (GUIctrlread($FilterCombo))
    If $cde_FileExt = "*.txt" Then
    $cde_FileExtStr = ".+\.(txt|TXT)"
    ElseIf $cde_FileExt = "*.doc | docx" Then
    $cde_FileExtStr = ".+\.(doc|DOC|docx|DOCX)"
    ElseIf $cde_FileExt = "*.xls | xlsx | xlsm" Then
    ;~ $cde_FileExtStr = ".+\.(xls|xlsx)"
    $cde_FileExtStr = ".+\.(xls|xlsx|XLS|XLSX)"
    ElseIf $cde_FileExt = "*.nsf | ntf" Then
    $cde_FileExtStr = ".+\.(nsf|NSF|ntf|NTF)"
    ElseIf $cde_FileExt = "*.*" Then
    $cde_FileExtStr = ""
    Else
    MsgBox(0,"",$cde_FileExt)
    $cde_FileExt = StringReplace($cde_FileExt,'*.', '.+\.')
    MsgBox(0,"",$cde_FileExt)
    $cde_FileExtStr = $cde_FileExt
    EndIf

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

    If $cde_FileExtStr="" Then
    MsgBox(0,"","Vz1 : " & $cde_Verz1 & @CRLF & "Vz2 : " & $cde_Verz2 & @CRLF & "Filter : <NUL>")
    Else
    MsgBox(0,"","Vz1 : " & $cde_Verz1 & @CRLF & "Vz2 : " & $cde_Verz2 & @CRLF & "Filter : " & $cde_FileExtStr)
    EndIf

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

    $aChecked = _Check($cde_Verz1, $cde_Verz2, 0)
    If $cde_FileExtStr = "" Then
    _ArrayDisplay($aChecked,"Datei Abgleich - Filter: [*.*]")
    Else
    _ArrayDisplay($aChecked,"Datei Abgleich - Filter: [" & $cde_FileExtStr & "]")
    EndIf

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

    Case $Button2Cancel
    ExitLoop
    Case $GUI_EVENT_CLOSE

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

    Exit

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

    EndSwitch
    WEnd

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

    Func _Check($cde_Verz1, $cde_Verz2, $iDays)
    ;~ $aReturn1 = _RecursiveFileListToArray($cde_Verz1, '.+\.(txt|TXT|jpg)', 1, 1, @CRLF, $cde_Verz1) ; Alle Dateien im ausgewählten Ordner und Unterordnern)
    ;~ $aReturn2 = _RecursiveFileListToArray($cde_Verz2, '.+\.(txt|TXT|jpg)', 1, 1, @CRLF, $cde_Verz2) ; Alle Dateien im ausgewählten Ordner und Unterordnern)

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

    $aReturn1 = _RecursiveFileListToArray($cde_Verz1, $cde_FileExtStr, 1, 1, @CRLF, $cde_Verz1) ; Alle Dateien im ausgewählten Ordner und Unterordnern)
    $aReturn2 = _RecursiveFileListToArray($cde_Verz2, $cde_FileExtStr, 1, 1, @CRLF, $cde_Verz2) ; Alle Dateien im ausgewählten Ordner und Unterordnern)
    Local $aResult[$aReturn1[0] + $aReturn2[0]][4]
    $iNew = 1

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

    _ArrayDisplay($aReturn1,"Array Vrz1")
    _ArrayDisplay($aReturn2,"Array Vrz2")

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

    For $i = 1 To $aReturn1[0]
    $iPos = _ArraySearch($aReturn2, $aReturn1[$i])
    If $iPos > -1 Then ;datei existiert auch um 2. Verzeichnis
    _ArrayDelete($aReturn2, $iPos) ;damit in $aReturn2 nur Dateien übrigbleiben die nicht i $aReturn1 sind
    $aReturn2[0] -= 1
    Else
    $aResult[$iNew][0] = $aReturn1[$i]
    $aResult[$iNew][2] = ''
    $aResult[$iNew][3] = "nur auf '" & $cde_Verz1 & "' vorhanden" ;Kenzeichnung dass Datei nur in 1
    $iNew += 1
    EndIf
    Next
    ;~ _ArrayDisplay($aResult)
    For $i = 1 To $aReturn2[0]
    $aResult[$iNew][0] = $aReturn2[$i]
    $aResult[$iNew][3] = "nur auf '" & $cde_Verz2 & "' vorhanden" ;Kenzeichnung dass Datei nur in 2
    $iNew += 1
    Next
    $aResult[0][0] = $iNew - 1
    ReDim $aResult[$iNew][4]
    $aResult[0][1] = $cde_Verz1
    $aResult[0][2] = $cde_Verz2
    $aResult[0][3] = "Differenz"
    Return $aResult
    EndFunc ;==>_Check

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

    ;===============================================================================
    ; Function Name: _RecursiveFileListToArray($sPath, $sPattern, $iFlag = 0, $iFormat = 1, $sDelim = @CRLF)
    ; Description:: gibt Verzeichnisse und/oder Dateien (rekursiv) 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
    ; $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)
    ;modified: autoBert um den ursprünglich übergebenen Ordner wegzulassen
    ;===============================================================================

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

    ;~ Pattern zum Filtern - cde ^(([a-zA-Z]:)|(\\{2}\w+)\$?)(\\(\w[\w ]*))+\.(nsf|NSF|ntf|NTF)$
    ;~ ^([a-zA-z]:((\\([-*\.*\w+\s+\d+]+)|(\w+)\\)+)(\w+.nsf)|(\w+.NSF)|(\w+.ntf)|(\w+.NTF))$
    ;~ .+\.(nsf|ntf)

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

    Func _RecursiveFileListToArray($sPath, $sPattern, $iFlag = 0, $iFormat = 1, $sDelim = @CRLF, $sExlude = '')
    Local $hSearch, $sFile, $sReturn = ''
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    $hSearch = FileFindFirstFile($sPath & '*.*')
    If @error Or $hSearch = -1 Then Return SetError(1, 0, $sReturn)
    While True
    $sFile = FileFindNextFile($hSearch)
    If @error Then ExitLoop
    If StringInStr(FileGetAttrib($sPath & $sFile), 'D') Then
    If StringRegExp($sPath & $sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 2) Then $sReturn &= $sPath & $sFile & '\' & $sDelim
    $sReturn &= _RecursiveFileListToArray($sPath & $sFile & '\', $sPattern, $iFlag, 0, $sDelim, $sExlude)
    ContinueLoop
    EndIf
    If StringRegExp($sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 1) Then $sReturn &= $sPath & $sFile & $sDelim
    WEnd
    FileClose($hSearch)
    $sReturn = StringReplace($sReturn, $sExlude, "")
    If $iFormat Then Return StringSplit(StringTrimRight($sReturn, StringLen($sDelim)), $sDelim, $iFormat)
    Return $sReturn
    EndFunc ;==>_RecursiveFileListToArray

    [/autoit]

    Jetzt hoffe ich mal auf das Wissen hier und bedanke mich schon mal

    Gruss
    ugt100

  • Hi, erstmal danke für so eine Detaillierte Fehlerbeschreibung und auch allgemeine Beschreibung. Sieht man echt selten :)

    Ich kann deinen Fehler nicht ganz nachvollziehen. Bei mir funktionieren ALLE Filter ohne Abbruch, ohne Fehler. Der einzige Fehler welcher mir unter gekommen ist, war als ich einen Ordner angegeben hab, welcher nicht existiert hat. _RecursiveFileListToArray hat dementsprechend kein Array zurück gegeben und in Zeile 104

    [autoit]

    Local $aResult[$aReturn1[0] + $aReturn2[0]][4]

    [/autoit]


    konnte $aResult nicht definiert werden, da $aReturn1 kein Array war. Da würde ich dir noch eine Fehlerprüfung empfehlen. Sonst kann ich dir leider nicht helfen.

    Grüße ErrorKid

  • Hi Errorkid,

    Danke für die 'Blumen' (naja ich denke halt, wenn man was will sollte man es auch ordentlich beschreiben oder ???)

    Tja seltsame Geschichte.
    Klar ist wenn die Suchje auf ein Verzeichnis gemacht wird was nicht existent ist, das dadurch das entsprechende Array nicht erzeugt werden kann und dann das Script auf einen Fehler läuft.

    Dann werde ich im nächsten Step mal den Rechner wechseln und / oder eine portable Version auf einer anderen Maschine testen.
    (denn an den RegEx Filtern kann es ja eher nicht liegen). Vllt ist das auch bedingt durch Win8 .... schaun mer mal ....


    DANKE für die prompte Antwort