wljdflgio Posted August 30, 2020 Share Posted August 30, 2020 (edited) According to the manual, _FileListToArrayRec uses regular expressions to check the mask values. Nevertheless a correct mask according to https://www.autoitscript.com/autoit3/docs/tutorials/regexp/regexp.htm does not work. If I use mask "*.001;*.002;" then files a.001 and a.002 are matched. If I use ".[0-9]{3} They are not. Am I doing something wrong or is _FileListToArrayRec just not fully supporting Regex? Thanks Edited August 30, 2020 by wljdflgio Link to comment Share on other sites More sharing options...
Nine Posted August 30, 2020 Share Posted August 30, 2020 I believe there is a documentation error in _FileListToArray help file. After looking at _FileListToArrayRec code, there is no RegEx involved in the function. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
pseakins Posted August 30, 2020 Share Posted August 30, 2020 I think the help for _FileListToArray may be a misleading. It says that _FileListToArrayRec "compares all subfolders to the specified filter using a RegEx" but this does not necessarily mean that you can use a regular expression. I think it means that the function internally converts the arguments into some form of regular expression which it then applies. Phil Seakins Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted August 31, 2020 Moderators Share Posted August 31, 2020 Hi, pseakins has it correctly. The filter you enter is internally converted into a RegEx to speed up the comparison code when searching - but the filter must be of the form indicated in the Help file. Of interest I did produce a version of the function which would accept a RegEx as filter but it was never adopted - do people think this might be worth looking into again? M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
Musashi Posted August 31, 2020 Share Posted August 31, 2020 16 minutes ago, Melba23 said: Of interest I did produce a version of the function which would accept a RegEx as filter but it was never adopted - do people think this might be worth looking into again? A crystal clear YES "In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move." Link to comment Share on other sites More sharing options...
AspirinJunkie Posted August 31, 2020 Share Posted August 31, 2020 (edited) I am pretty sure that a wide range of user-defined functions already exists for exactly this use case. Like many others, i have written a function that lists files/folders recursively with the possibility to filter by RegEx. But it has a few extras: On the one hand you can directly pass multiple search locations. On the other hand you can do much more complex filtering, because you can pass your own matching function: expandcollapse popup; #FUNCTION# ====================================================================================== ; Name ..........: _listFilesFlexible() ; Description ...: Finds files and/or folders in a directory tree with multiple filtering options ; Syntax ........: _listFilesFlexible($sSD, [Const $sPat = '', [Const $iF = 3, [Const $1BASED = 0]]]) ; Parameters ....: $sSD - search location[s] (you can separate multiple with "|") ; Const $sPat - [optional] regular expression for filename matching or a function pointer for more complex matching ; remark: RegEx is normally case-sensitive - add (?i) at pattern start to switch to case-insensitive ; "" (Default): No filename matching - all elements will be retrieved ; Const $iF - [optional] 1=only files, 2=only folders, 3=files and folders (default:3) ; Const $1BASED - [optional] 0= zero-based - no count in $Array[0] (Default), 1= 1-based - count in $Array[0] ; Return values .: Success - Return Array with Matches ; Failure - Return "" and set @error ; Author ........: AspirinJunkie ; ================================================================================================= Func _listFilesFlexible($sSD, Const $sPat = '', Const $iF = 3, Const $1BASED = 0) Local $cEl = $1BASED, $cAS = 1 ; counter for number of elements vs. current array size Local $aRet[1] = [0] Local $aSD = StringSplit($sSD, '|', 1) ; stack for search folders Local $FFFF, $FFNF, $sDir, $sP Local $hDLL = DllOpen('kernel32.dll') Local $p_F = DllCall($hDLL, "ptr", "GetProcAddress", "handle", DllCall($hDLL, "handle", "GetModuleHandleW", "wstr", "kernel32.dll")[0], "str", "GetFileAttributesW")[0] ; get the function address of GetModuleHandleW If Not ($iF = 3 Or $iF = 1 Or $iF = 2) Then Return SetError(3, 0, "") If $sPat = "" Then Do ; pull next dir from stack $sDir = $aSD[$aSD[0]] & "\" $aSD[0] -= 1 $FFFF = FileFindFirstFile($sDir & '*') If $FFFF <> -1 Then Do $FFNF = FileFindNextFile($FFFF) If @error Then ExitLoop $sP = $sDir & $FFNF If @extended Then ; folder If BitAND($iF, 2) Then ; matched dir If $cEl >= $cAS Then $cAS += $cAS ReDim $aRet[$cAS] EndIf $aRet[$cEl] = $sP $cEl += 1 EndIf ; ignore reparse points If BitAND(DllCallAddress('dword', $p_F, 'wstr', $sP)[0], 0x400) Then ContinueLoop ; push subfolder to folder stack $aSD[0] += 1 If $aSD[0] = UBound($aSD) Then ReDim $aSD[UBound($aSD) * 2] $aSD[$aSD[0]] = $sP ElseIf BitAND($iF, 1) Then ; matched file If $cEl >= $cAS Then $cAS += $cAS ReDim $aRet[$cAS] EndIf $aRet[$cEl] = $sP $cEl += 1 EndIf Until 0 FileClose($FFFF) EndIf Until $aSD[0] = 0 ElseIf IsFunc($sPat) Then ; $sPat = function Do ; pull next dir from stack $sDir = $aSD[$aSD[0]] & "\" $aSD[0] -= 1 $FFFF = FileFindFirstFile($sDir & '*') If $FFFF <> -1 Then Do $FFNF = FileFindNextFile($FFFF) If @error Then ExitLoop $sP = $sDir & $FFNF If @extended Then ; folder If BitAND($iF, 2) And $sPat($sP) Then ; match by function If $cEl >= $cAS Then $cAS += $cAS ReDim $aRet[$cAS] EndIf $aRet[$cEl] = $sP $cEl += 1 EndIf ; ignore reparse points If BitAND(DllCallAddress('dword', $p_F, 'wstr', $sP)[0], 0x400) Then ContinueLoop ; push subfolder to folder stack $aSD[0] += 1 If $aSD[0] = UBound($aSD) Then ReDim $aSD[UBound($aSD) * 2] $aSD[$aSD[0]] = $sP ; file ElseIf BitAND($iF, 1) And $sPat($sP) Then ; match by function If $cEl >= $cAS Then $cAS += $cAS ReDim $aRet[$cAS] EndIf $aRet[$cEl] = $sP $cEl += 1 EndIf Until 0 FileClose($FFFF) EndIf Until $aSD[0] = 0 Else ; $sPat = regex Do ; pull next dir from stack $sDir = $aSD[$aSD[0]] & "\" $aSD[0] -= 1 $FFFF = FileFindFirstFile($sDir & '*') If $FFFF <> -1 Then Do $FFNF = FileFindNextFile($FFFF) If @error Then ExitLoop $sP = $sDir & $FFNF If @extended Then ; folder If BitAND($iF, 2) And StringRegExp($FFNF, $sPat) Then ; match by regex If $cEl >= $cAS Then $cAS += $cAS ReDim $aRet[$cAS] EndIf $aRet[$cEl] = $sP $cEl += 1 EndIf ; ignore reparse points If BitAND(DllCallAddress('dword', $p_F, 'wstr', $sP)[0], 0x400) Then ContinueLoop ; push subfolder to folder stack $aSD[0] += 1 If $aSD[0] = UBound($aSD) Then ReDim $aSD[UBound($aSD) * 2] $aSD[$aSD[0]] = $sP ElseIf BitAND($iF, 1) And StringRegExp($FFNF, $sPat) Then ; match by regex If $cEl >= $cAS Then $cAS += $cAS ReDim $aRet[$cAS] EndIf $aRet[$cEl] = $sP $cEl += 1 EndIf Until 0 FileClose($FFFF) EndIf Until $aSD[0] = 0 EndIf DllClose($hDLL) If $1BASED = 1 Then $aRet[0] = $cEl - 1 ReDim $aRet[$cEl] Return $aRet EndFunc ;==>_listFilesFlexible Example for simple RegEx usage: #include <Array.au3> ; all dll-files in system dir $aFiles = _listFilesFlexible(@SystemDir, "(?i)\.dll$", 1) _ArrayDisplay($aFiles) More complex example (multiple search folders with search by file size): #include <Array.au3> ; all dll files in system dir AND user profile dir which are greater than 5 mb $aFiles = _listFilesFlexible(@SystemDir & "|" & @UserProfileDir, _myCheck, 1) _ArrayDisplay($aFiles) Func _myCheck(Const $sPath) If StringRight($sPath, 4) <> ".dll" Then Return 0 If FileGetSize($sPath) > 5242880 Then Return 1 Return 0 EndFunc Edited September 24, 2020 by AspirinJunkie performance improved of function dogisay and Musashi 2 Link to comment Share on other sites More sharing options...
wljdflgio Posted September 1, 2020 Author Share Posted September 1, 2020 Interesting, because wildcards * and ? did work for me, so some sub-set of RegEx seems to work. Link to comment Share on other sites More sharing options...
AspirinJunkie Posted September 1, 2020 Share Posted September 1, 2020 2 hours ago, wljdflgio said: Interesting, because wildcards * and ? did work for me, so some sub-set of RegEx seems to work. These are not complete regular expressions but only two placeholders provided by the underlying Windows API function >>FindFirstFileA<<. There is no more than these two. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now