#include ;#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7 ; ##################################################################################################################################################### ; Example code ; Get AutoIt installation folder Global $sRootFolder = StringRegExpReplace(StringLeft(@AutoItExe, StringInStr(@AutoItExe, "\", Default, -1)), "(.*)\\Beta", "$1") ConsoleWrite($sRootFolder & @CRLF) ; Current UDF implementation - returns ".exe", "_x64.exe", "Wrapper" and "Help" files Local $nBegin = TimerInit() Local $aList = _FileListToArrayRec($sRootFolder, "AutoIt3*.exe", $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH) ConsoleWrite(TimerDiff($nBegin) & @CRLF) ; ~1800ms _ArrayDisplay($aList, "Current UDF", Default, 8) ; Modded UDF using a Regex in the mask to return only ".exe" and "Help" files $nBegin = TimerInit() $aList = _FileListToArrayRec_Mod($sRootFolder, "::(?i)^autoit3(?:help)?\.exe$::", $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH) ConsoleWrite(@error & " - " & @extended & @CRLF) ConsoleWrite(TimerDiff($nBegin) & @CRLF) _ArrayDisplay($aList, "Mod UDF with Regex", Default, 8) ; Define user function including the regex to return only ".exe" and "Help" files Local $hFunc = _UserFunc_1 $nBegin = TimerInit() ; Pass user function in place of filter parameter <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $aList = _FileListToArrayRec_Mod($sRootFolder, $hFunc, $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH) ConsoleWrite(TimerDiff($nBegin) & @CRLF) _ArrayDisplay($aList, "Mod UDF with Func", Default, 8) ; Define user function which also returns the file timestamp in the array $hFunc = _UserFunc_2 $nBegin = TimerInit() ; Pass user function in place of filter parameter <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $aList = _FileListToArrayRec_Mod($sRootFolder, $hFunc, $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH, 2) ; Return a 2D array <<<<<<<<<<<<<<<<<<<< ConsoleWrite(TimerDiff($nBegin) & @CRLF) _ArrayDisplay($aList, "Mod UDF with Func & 2D array", Default, 8) ; ##################################################################################################################################################### ; The user defined functions to be called Func _UserFunc_1($sPath, $sName, $sAttribs) ; Must use these 3 parameters <<<<<<<<<<<<<<<<<<<<<<<<< #forceref $sPath, $sAttribs If StringRegExp($sName, "(?i)^autoit3(?:help)?\.exe$") Then Return $sPath & $sName ; Return a single item to be added to the return list Else Return SetError(1) ; Return an error if nothing is to be added EndIf EndFunc Func _UserFunc_2($sPath, $sName, $sAttribs) ; Must use these 3 parameters <<<<<<<<<<<<<<<<<<<<<<<<< #forceref $sPath, $sAttribs If StringRegExp($sName, "(?i)^autoit3(?:help)?\.exe$") Then Local $aRet[2] = [$sPath & $sName, FileGetTime($sPath & $sName, Default, 1)] Return $aRet ; Return an array which must match the number of colums defined in the FLTAR call Else Return SetError(1) ; Return an error if nothing is to be added EndIf EndFunc ; ##################################################################################################################################################### ; The new UDF functions Func _FileListToArrayRec_Mod($sFilePath, $vMask = "*", $iReturn = $FLTAR_FILESFOLDERS, $iRecur = $FLTAR_NORECUR, $iSort = $FLTAR_NOSORT, $iReturnPath = $FLTAR_RELPATH, $iUserRet_Cols = 1) If Not FileExists($sFilePath) Then Return SetError(1, 1, "") ; Check for Default keyword If $vMask = Default Then $vMask = "*" If $iReturn = Default Then $iReturn = $FLTAR_FILESFOLDERS If $iRecur = Default Then $iRecur = $FLTAR_NORECUR If $iSort = Default Then $iSort = $FLTAR_NOSORT If $iReturnPath = Default Then $iReturnPath = $FLTAR_RELPATH ; Check for valid recur value If $iRecur > 1 Or Not IsInt($iRecur) Then Return SetError(1, 6, "") Local $bLongPath = False ; Check for valid path If StringLeft($sFilePath, 4) == "\\?\" Then $bLongPath = True EndIf Local $sFolderSlash = "" ; Check if folders should have trailing \ and ensure that initial path does have one If StringRight($sFilePath, 1) = "\" Then $sFolderSlash = "\" Else $sFilePath = $sFilePath & "\" EndIf Local $asFolderSearchList[100] = [1] ; Add path to folder search list $asFolderSearchList[1] = $sFilePath Local $hFunc = 0 ; Check if custom function set If IsFunc($vMask) Then $hFunc = $vMask $vMask = "*" $iSort = $FLTAR_NOSORT EndIf Local $iMaxLevel = 0 ; If required, determine \ count for max recursive level setting If $iRecur < 0 Then StringReplace($sFilePath, "\", "", 0, $STR_NOCASESENSEBASIC) $iMaxLevel = @extended - $iRecur EndIf Local $iHide_HS = 0, $sHide_HS = "", $iHide_Link = 0 Local $sInclude_List = "*", $sExclude_List = "", $sExclude_List_Folder = "" Local $sInclude_File_Mask = ".+", $sInclude_Folder_Mask = ".+", $sExclude_File_Mask = ":", $sExclude_Folder_Mask = ":" Local $asReturnList[100] = [0] If $hFunc = 0 Then ; Check for H or S omitted If BitAND($iReturn, 4) Then $iHide_HS += 2 $sHide_HS &= "H" $iReturn -= 4 EndIf If BitAND($iReturn, 8) Then $iHide_HS += 4 $sHide_HS &= "S" $iReturn -= 8 EndIf ; Check for link/junction omitted If BitAND($iReturn, 16) Then $iHide_Link = 0x400 $iReturn -= 16 EndIf ; Check for possible RegEx "OR" within mask parameters and replace with UniCode user character Local $iCount = 1, $iPos_Begin, $iPos_End While 1 $iPos_Begin = StringInStr($vMask, "::", $STR_NOCASESENSEBASIC, $iCount) If $iPos_Begin = 0 Then ExitLoop ; No further RegEx bound found so continue $iPos_End = StringInStr($vMask, "::", $STR_NOCASESENSEBASIC, $iCount + 1) If $iPos_End = 0 Then Return SetError(1, 2, "") ; No matching RegEx bound found so error Else ; Move through RegEx replacing any "OR" found For $i = $iPos_Begin To $iPos_End If StringMid($vMask, $i, 1) = "|" Then $vMask = StringMid($vMask, 1, $i - 1) & ChrW(0xFAB1) & StringMid($vMask, $i + 1) EndIf Next EndIf ; Look for another RegEx $iCount += 2 WEnd ; Check number of mask parameters Local $aMaskSplit = StringSplit($vMask, "|") ; Check for multiple sections and set values - resetting RegEx "OR" if needed Switch $aMaskSplit[0] Case 3 $sExclude_List_Folder = StringReplace($aMaskSplit[3], ChrW(0xFAB1), "|") ContinueCase Case 2 $sExclude_List = StringReplace($aMaskSplit[2], ChrW(0xFAB1), "|") ContinueCase Case 1 $sInclude_List = StringReplace($aMaskSplit[1], ChrW(0xFAB1), "|") EndSwitch ; Create Include mask for files If $sInclude_List <> "*" Then If Not __FLTAR_ListToMask_Regex($sInclude_File_Mask, $sInclude_List) Then Return SetError(1, 2, "") EndIf ; Set Include mask for folders Switch $iReturn Case 0 ; Folders affected by mask if not recursive Switch $iRecur Case 0 ; Folders match mask for compatibility $sInclude_Folder_Mask = $sInclude_File_Mask EndSwitch Case 2 ; Folders affected by mask $sInclude_Folder_Mask = $sInclude_File_Mask EndSwitch ; Create Exclude List mask for files If $sExclude_List <> "" Then If Not __FLTAR_ListToMask_Regex($sExclude_File_Mask, $sExclude_List) Then Return SetError(1, 3, "") EndIf ; Create Exclude mask for folders If $iRecur Then If $sExclude_List_Folder Then If Not __FLTAR_ListToMask_Regex($sExclude_Folder_Mask, $sExclude_List_Folder) Then Return SetError(1, 4, "") EndIf ; If folders only If $iReturn = 2 Then ; Folders affected by normal mask $sExclude_Folder_Mask = $sExclude_File_Mask EndIf Else ; Folders affected by normal mask $sExclude_Folder_Mask = $sExclude_File_Mask EndIf ; Prepare for DllCall if required If $iHide_Link Then Local $tFile_Data = DllStructCreate("struct;align 4;dword FileAttributes;uint64 CreationTime;uint64 LastAccessTime;uint64 LastWriteTime;" & _ "dword FileSizeHigh;dword FileSizeLow;dword Reserved0;dword Reserved1;wchar FileName[260];wchar AlternateFileName[14];endstruct") Local $hDLL = DllOpen('kernel32.dll'), $aDLL_Ret EndIf Else ; Limit return parameter $iReturn = BitAnd($iReturn, 3) ; If user function then create correct sized return array If $iUserRet_Cols > 1 Then Local $asReturnList[100][$iUserRet_Cols] = [[0]] EndIf EndIf ; Verify other parameters If Not ($iReturn = 0 Or $iReturn = 1 Or $iReturn = 2) Then Return SetError(1, 5, "") If Not ($iSort = 0 Or $iSort = 1 Or $iSort = 2) Then Return SetError(1, 7, "") If Not ($iReturnPath = 0 Or $iReturnPath = 1 Or $iReturnPath = 2) Then Return SetError(1, 8, "") Local $asFileMatchList = $asReturnList, $asRootFileMatchList = $asReturnList, $asFolderMatchList = $asReturnList Local $bFolder = False, $hSearch = 0, $sCurrentPath = "", $sName = "", $sUserReturnPath = "", $vFuncReturn Local $iAttribs = 0, $sAttribs = "" Local $asFolderFileSectionList[100][2] = [[0, 0]] ; User function not defined If $hFunc = 0 Then Local $aSortPathData[2] ; Search within listed folders While $asFolderSearchList[0] > 0 ; Set path to search $sCurrentPath = $asFolderSearchList[$asFolderSearchList[0]] ; Reduce folder search list count $asFolderSearchList[0] -= 1 ; Determine return path to add to file/folder name Switch $iReturnPath ; Case 0 ; Name only ; Leave as "" Case 1 ;Relative to initial path $sUserReturnPath = StringReplace($sCurrentPath, $sFilePath, "") Case 2 ; Full path If $bLongPath Then $sUserReturnPath = StringTrimLeft($sCurrentPath, 4) Else $sUserReturnPath = $sCurrentPath EndIf EndSwitch ; Get search handle - use code matched to required listing If $iHide_Link Then ; Use DLL code $aDLL_Ret = DllCall($hDLL, 'handle', 'FindFirstFileW', 'wstr', $sCurrentPath & "*", 'struct*', $tFile_Data) If @error Or Not $aDLL_Ret[0] Then ContinueLoop EndIf $hSearch = $aDLL_Ret[0] Else ; Use native code $hSearch = FileFindFirstFile($sCurrentPath & "*") ; If folder empty move to next in list If $hSearch = -1 Then ContinueLoop EndIf EndIf ; If sorting files and folders with paths then store folder name and position of associated files in list If $iReturn = 0 And $iSort And $iReturnPath Then $aSortPathData[0] = $sUserReturnPath $aSortPathData[1] = $asFileMatchList[0] + 1 __FLTAR_AddToList_Mod($asFolderFileSectionList, $aSortPathData) EndIf $sAttribs = '' ; Search folder - use code matched to required listing While 1 ; Use DLL code If $iHide_Link Then ; Use DLL code $aDLL_Ret = DllCall($hDLL, 'int', 'FindNextFileW', 'handle', $hSearch, 'struct*', $tFile_Data) ; Check for end of folder If @error Or Not $aDLL_Ret[0] Then ExitLoop EndIf ; Extract data $sName = DllStructGetData($tFile_Data, "FileName") ; Check for .. return - only returned by the DllCall If $sName = ".." Then ContinueLoop EndIf $iAttribs = DllStructGetData($tFile_Data, "FileAttributes") ; Check for hidden/system attributes and skip if found If $iHide_HS And BitAND($iAttribs, $iHide_HS) Then ContinueLoop EndIf ; Check for link attribute and skip if found If BitAND($iAttribs, $iHide_Link) Then ContinueLoop EndIf ; Set subfolder flag $bFolder = False If BitAND($iAttribs, 16) Then $bFolder = True EndIf Else ; Reset folder flag $bFolder = False ; Use native code $sName = FileFindNextFile($hSearch, 1) ; Check for end of folder If @error Then ExitLoop EndIf $sAttribs = @extended ; Check for folder If StringInStr($sAttribs, "D") Then $bFolder = True EndIf ; Check for Hidden/System If StringRegExp($sAttribs, "[" & $sHide_HS & "]") Then ContinueLoop EndIf EndIf ; If folder then check whether to add to search list If $bFolder Then Select Case $iRecur < 0 ; Check recur depth StringReplace($sCurrentPath, "\", "", 0, $STR_NOCASESENSEBASIC) If @extended < $iMaxLevel Then ContinueCase ; Check if matched to masks EndIf Case $iRecur = 1 ; Full recur If Not StringRegExp($sName, $sExclude_Folder_Mask) Then ; Add folder unless excluded __FLTAR_AddToList_Mod($asFolderSearchList, $sCurrentPath & $sName & "\") EndIf ; Case $iRecur = 0 ; Never add ; Do nothing EndSelect EndIf If $iSort Then ; Save in relevant folders for later sorting If $bFolder Then If StringRegExp($sName, $sInclude_Folder_Mask) And Not StringRegExp($sName, $sExclude_Folder_Mask) Then __FLTAR_AddToList_Mod($asFolderMatchList, $sUserReturnPath & $sName & $sFolderSlash) EndIf Else If StringRegExp($sName, $sInclude_File_Mask) And Not StringRegExp($sName, $sExclude_File_Mask) Then ; Select required list for files If $sCurrentPath = $sFilePath Then __FLTAR_AddToList_Mod($asRootFileMatchList, $sUserReturnPath & $sName) Else __FLTAR_AddToList_Mod($asFileMatchList, $sUserReturnPath & $sName) EndIf EndIf EndIf Else ; Save directly in return list If $bFolder Then If $iReturn <> 1 And StringRegExp($sName, $sInclude_Folder_Mask) And Not StringRegExp($sName, $sExclude_Folder_Mask) Then __FLTAR_AddToList_Mod($asReturnList, $sUserReturnPath & $sName & $sFolderSlash) EndIf Else If $iReturn <> 2 And StringRegExp($sName, $sInclude_File_Mask) And Not StringRegExp($sName, $sExclude_File_Mask) Then __FLTAR_AddToList_Mod($asReturnList, $sUserReturnPath & $sName) EndIf EndIf EndIf WEnd ; Close current search FileClose($hSearch) WEnd Else ; User function defined While $asFolderSearchList[0] > 0 ; Set path to search $sCurrentPath = $asFolderSearchList[$asFolderSearchList[0]] ; Reduce folder search list count $asFolderSearchList[0] -= 1 ; Get search handle - use code matched to required listing $hSearch = FileFindFirstFile($sCurrentPath & "*") ; If folder empty move to next in list If $hSearch = -1 Then ContinueLoop EndIf ; Search folder - use code matched to required listing While 1 ; Reset folder flag $bFolder = 0 ; Get next file $sName = FileFindNextFile($hSearch, 1) ; Check for end of folder If @error Then ExitLoop EndIf $sAttribs = @extended ; Check for folder If StringInStr($sAttribs, "D") Then $bFolder = 1 EndIf ; If folder then check whether to add to search list If $bFolder Then Select Case $iRecur < 0 ; Check recur depth StringReplace($sCurrentPath, "\", "", 0, $STR_NOCASESENSEBASIC) If @extended < $iMaxLevel Then ContinueCase ; Check if matched to masks EndIf Case $iRecur = 1 ; Full recur __FLTAR_AddToList_Mod($asFolderSearchList, $sCurrentPath & $sName & "\") ; Case $iRecur = 0 ; Never add ; Do nothing EndSelect EndIf ; pass item details to user function $vFuncReturn = $hFunc($sCurrentPath, $sName, $sAttribs) ; Add any returned data to array If Not @error Then __FLTAR_AddToList_Mod($asReturnList, $vFuncReturn) EndIf WEnd ; Close current search FileClose($hSearch) WEnd EndIf ; Close the DLL if needed If $iHide_Link Then DllClose($hDLL) EndIf If $hFunc <> 0 Then If $iUserRet_Cols > 1 Then ; Check if any file/folders have been added If $asReturnList[0][0] = 0 Then Return SetError(1, 9, "") ; Remove any unused return list elements from last ReDim ReDim $asReturnList[$asReturnList[0][0] + 1][$iUserRet_Cols] Else If $asReturnList[0] = 0 Then Return SetError(1, 9, "") ReDim $asReturnList[$asReturnList[0] + 1] EndIf Else ; Sort results if required If $iSort Then Switch $iReturn Case 2 ; Folders only ; Check if any folders found If $asFolderMatchList[0] = 0 Then Return SetError(1, 9, "") ; Correctly size folder match list ReDim $asFolderMatchList[$asFolderMatchList[0] + 1] ; Copy size folder match array $asReturnList = $asFolderMatchList ; Simple sort list __ArrayDualPivotSort($asReturnList, 1, $asReturnList[0]) Case 1 ; Files only ; Check if any files found If $asRootFileMatchList[0] = 0 And $asFileMatchList[0] = 0 Then Return SetError(1, 9, "") If $iReturnPath = 0 Then ; names only so simple sort suffices ; Combine file match lists __FLTAR_AddFileLists($asReturnList, $asRootFileMatchList, $asFileMatchList) ; Simple sort combined file list __ArrayDualPivotSort($asReturnList, 1, $asReturnList[0]) Else ; Combine sorted file match lists __FLTAR_AddFileLists($asReturnList, $asRootFileMatchList, $asFileMatchList, 1) EndIf Case 0 ; Both files and folders ; Check if any root files or folders found If $asRootFileMatchList[0] = 0 And $asFolderMatchList[0] = 0 Then Return SetError(1, 9, "") If $iReturnPath = 0 Then ; names only so simple sort suffices ; Combine file match lists __FLTAR_AddFileLists($asReturnList, $asRootFileMatchList, $asFileMatchList) ; Set correct count for folder add $asReturnList[0] += $asFolderMatchList[0] ; Resize and add file match array ReDim $asFolderMatchList[$asFolderMatchList[0] + 1] _ArrayConcatenate($asReturnList, $asFolderMatchList, 1) ; Simple sort final list __ArrayDualPivotSort($asReturnList, 1, $asReturnList[0]) Else ; Size return list Local $asReturnList[$asFileMatchList[0] + $asRootFileMatchList[0] + $asFolderMatchList[0] + 1] $asReturnList[0] = $asFileMatchList[0] + $asRootFileMatchList[0] + $asFolderMatchList[0] ; Sort root file list __ArrayDualPivotSort($asRootFileMatchList, 1, $asRootFileMatchList[0]) ; Add the sorted root files at the top For $i = 1 To $asRootFileMatchList[0] $asReturnList[$i] = $asRootFileMatchList[$i] Next ; Set next insertion index Local $iNextInsertionIndex = $asRootFileMatchList[0] + 1 ; Sort folder list __ArrayDualPivotSort($asFolderMatchList, 1, $asFolderMatchList[0]) Local $sFolderToFind = "" ; Work through folder list For $i = 1 To $asFolderMatchList[0] ; Add folder to return list $asReturnList[$iNextInsertionIndex] = $asFolderMatchList[$i] $iNextInsertionIndex += 1 ; Format folder name for search If $sFolderSlash Then $sFolderToFind = $asFolderMatchList[$i] Else $sFolderToFind = $asFolderMatchList[$i] & "\" EndIf Local $iFileSectionEndIndex = 0, $iFileSectionStartIndex = 0 ; Find folder in FolderFileSectionList For $j = 1 To $asFolderFileSectionList[0][0] ; If found then deal with files If $sFolderToFind = $asFolderFileSectionList[$j][0] Then ; Set file list indexes $iFileSectionStartIndex = $asFolderFileSectionList[$j][1] If $j = $asFolderFileSectionList[0][0] Then $iFileSectionEndIndex = $asFileMatchList[0] Else $iFileSectionEndIndex = $asFolderFileSectionList[$j + 1][1] - 1 EndIf ; Sort files if required If $iSort = 1 Then __ArrayDualPivotSort($asFileMatchList, $iFileSectionStartIndex, $iFileSectionEndIndex) EndIf ; Add files to return list For $k = $iFileSectionStartIndex To $iFileSectionEndIndex $asReturnList[$iNextInsertionIndex] = $asFileMatchList[$k] $iNextInsertionIndex += 1 Next ExitLoop EndIf Next Next EndIf EndSwitch Else ; No sort ; Check if any file/folders have been added If $asReturnList[0] = 0 Then Return SetError(1, 9, "") ; Remove any unused return list elements from last ReDim ReDim $asReturnList[$asReturnList[0] + 1] EndIf EndIf Return $asReturnList EndFunc ;==>_FileListToArrayRec_Regex Func __FLTAR_ListToMask_Regex(ByRef $vMask, $sList) ; Check if regex passed If StringLeft($sList, 2) = "::" And StringRight($sList, 2) = "::" Then ; Set it directly $vMask = StringTrimRight(StringTrimLeft($sList, 2), 2) ; Run basic check on regex pattern StringRegExp("::", $vMask) ; If pattern error If @error = 2 Then Return 0 Else ; If filename/wildcard string convert to regex ; Check for invalid characters within list If StringRegExp($sList, "\\|/|:|\<|\>|\|") Then Return 0 ; Strip WS and insert | for ; $sList = StringReplace(StringStripWS(StringRegExpReplace($sList, "\s*;\s*", ";"), $STR_STRIPLEADING + $STR_STRIPTRAILING), ";", "|") ; Convert to SRE pattern $sList = StringReplace(StringReplace(StringRegExpReplace($sList, "[][$^.{}()+\\-]", "\\$0"), "?", "."), "*", ".*?") ; Add prefix and suffix $vMask = "(?i)^(" & $sList & ")\z" EndIf Return 1 EndFunc ;==>__FLTAR_ListToMask Func __FLTAR_AddToList_Mod(ByRef $aList, $vData) If IsArray($vData) Then Local $iCols = UBound($vData) ; Check for bound mismatch If $iCols <> UBound($aList, 2) Then Return SetError(1) ; Increase list count $aList[0][0] += 1 ; Double list size if too small (fewer ReDim needed) If UBound($aList) <= $aList[0][0] Then ReDim $aList[UBound($aList) * 2][$iCols] ; Add data to 2D array For $i = 0 To $iCols - 1 $aList[$aList[0][0]][$i] = $vData[$i] Next Else ; Increase list count $aList[0] += 1 ; Double list size if too small (fewer ReDim needed) If UBound($aList) <= $aList[0] Then ReDim $aList[UBound($aList) * 2] ; Add value $aList[$aList[0]] = $vData EndIf EndFunc ;==>__FLTAR_AddToList