BaKaMu Posted June 27, 2009 Share Posted June 27, 2009 (edited) Wow! Now this is huge change.It looks like a filter could exclude a folder name from being returned by the function, but if $bRecursive is set, the files within that folder are still returned?If exclude removes a folder name from the list, the files names within that folder are still returned. Maybe that's cool.If you're retuning files only, should filters apply to folder names?I'm just trying to figure out filters, excludes and the $iFlag all interact, or how they should interact?A short explanation:Exclude filtering is done only once at the end of recursive calls and it's done only on filenames and/or foldernames (not full path of files and folders).It's a very simple extraction, so it's possible that a folder is extracted, but the files within this folders are returned.Normally i can life with that behavior, cause extraction is normally done on filenames.A possible solution maybe a additional exclude check shortly before the recursive call.(before the line: $sFileList &= _FileListToArrayEx($sPathItem & $sFile, $sFilter, $iFlag, $bRecursiv, "", 0))You have to prepare the $sExclude string and call -> If StringRegExp(StringRegExpReplace(... then ContinueLoop(like the Exclude part)This is surely more time consuming (every folder is checked) but maybe a alternative solution.So this is the old question: What is more important, speed or comfort?(and i don't know the answer) ;-) Edited June 27, 2009 by BaKaMu Link to comment Share on other sites More sharing options...
jpm Posted June 28, 2009 Share Posted June 28, 2009 So this is the old question: What is more important, speed or comfort?Both , but being logicalmy point of biew is if the folder is excluded the files cannot be return.I don't know how much speed it will cost if no exclude is used but I am sure you will find a solution for not impacting the speed in this caseNice work from everybody Link to comment Share on other sites More sharing options...
Spiff59 Posted June 28, 2009 Share Posted June 28, 2009 (edited) I think the debate is more simplicity versus complexity. I've nothing against complexity, if it is useful, but all the new parameters open up a lot of combinations of interaction between $iFlag, $sFilter, and any specified exclude strings. I mentioned a few of the possibilities in my last post. I would think that how these parms all work together would need to be determined, and documented. There is a bug in the exisitng production routine. If called with $iFlag as either 1 or 2, and no files/folders are found, it returns a one-element array, with nothing in the element. Only when called with an $iFlag of 0 will it return @error = 4. The "simple" version in this thread suffers from the same problem, which is alleviated by adding the two tests at the end of the while loops as in the example below. The recent "complex" version in this thread crashes under this circumstance. I'm unsure if the same two lines of code would also remedy that version. expandcollapse popupFunc _FileListToArray($sPath, $sFilter = "*", $iFlag = 0) Local $hSearch, $sFile, $sFileList, $sDelim = "|" If Not FileExists($sPath) Then Return SetError(1, 1, "") If StringRegExp($sFilter, "[\\/:<>|]") Or (Not StringStripWS($sFilter, 8)) Then Return SetError(2, 2, "") If StringRight($sPath, 1) <> "\" Then $sPath &= "\" If $iFlag > 3 Then $sDelim &= $sPath $iFlag -= 4 EndIf $hSearch = FileFindFirstFile($sPath & $sFilter) If @error Or $hSearch = -1 Then Return SetError(4, 4, "") Switch $iFlag Case 0; Files and Folders While 1 $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop $sFileList &= $sDelim & $sFile WEnd Case 1; Files Only While 1 $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop If @extended Then ContinueLoop; bypass folder $sFileList &= $sDelim & $sFile WEnd Case 2; Folders Only While 1 $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop If @extended = 0 Then ContinueLoop; bypass file $sFileList &= $sDelim & $sFile WEnd Case Else Return SetError(3, 3, "") EndSwitch FileClose($hSearch) If Not $sFileList Then Return SetError(4, 4, "") Return StringSplit(StringTrimLeft($sFileList, 1), "|") EndFunc;==>_FileListToArray Edited June 29, 2009 by Spiff59 Link to comment Share on other sites More sharing options...
BaKaMu Posted June 28, 2009 Share Posted June 28, 2009 (edited) Both , but being logical my point of biew is if the folder is excluded the files cannot be return. I don't know how much speed it will cost if no exclude is used but I am sure you will find a solution for not impacting the speed in this case Nice work from everybody Now i have made a new version, which do not return files/folders from excluded folders. For this i removed the Exclude part at the end of the recursion and check now each returned file/folder name from FileFindNextFile. To my surprise, the speed is not much lower (in some cases the speed is even higher). So thank you for the good advise :-) To all: Please check the new version for errors expandcollapse popup; #FUNCTION# ================================================================================================ ; Name: _FileListToArrayEx2 ; Description: full compatible _FileListToArray replacement (with more speed and additional features) ; additional: multi-path, multi-filter, multi exclude-filter, recursiv search ; optional full pathname ; Syntax: _FileListToArrayEx2([$sPath = @ScriptDir, [$sFilter = "*", [$iFlag = 0, [$bRecursiv = False, [$sExclude = "", [$iFormat = 1]]]]]]) ; Parameter(s): $sPath = optional: path to generate filelist for, multi paths separated with semicolon (ex: "C:\";D:\Temp") ; if no path is given then @ScriptDir is used ; $sFilter = optional: The filter to use. (default: "*") ; multi filters separated with semicolon (ex: *.exe; *.txt will find all .exe and .txt files) ; (Search the Autoit3 manual for the word "WildCards" for details) ; $iFlag = Optional: specifies whether to return files, folders or both ; 0 = (Default) Return both files and folders ; 1 = Return files only ; 2 = Return folders only ; $iFlag + 4 = Return Filenames and/or Folders incl full Path ; $bRecursiv = optional: true: recursive search in rootdir and subdirs ; False (default): search only in rootdir ; $sExclude = optional: exclude a file/folder from the list by all or part of its name, various statements delimited with semicolon ; (ex: Unins* will remove all files/folders that start with Unins) ; $iFormat = optional: return format ; 0 = String ( "|" delimited) ; 1 = (default) one-dimensional array, array[0] = number of files\folders returned ; 2 = one-dimensional array, 0-based ; Requirement(s): none ; Return Value(s): on success: string or array (dependent on $iFormat) ; Author(s): bernd670, Tlem, Spiff59, Zedna, KaFu, SmOke_N, GEOSoft, BaKaMu ; ================================================================================================= Func _FileListToArrayEx2($sPath = @ScriptDir, $sFilter = "*", $iFlag = 0, $bRecursiv = False, $sExclude = "", $iFormat = 1) Local $hSearch, $iPCount, $iFCount, $sFile, $TFlag = 0, $sFileList = "", $sTExclude = "" If $sPath = -1 Or $sPath = Default Then $sPath = @ScriptDir If $sFilter = -1 Or $sFilter = Default Then $sFilter = "*" If $iFlag = -1 Or $iFlag = Default Then $iFlag = 0 If $bRecursiv = Default Then $bRecursiv = False If $sExclude = -1 Or $sExclude = Default Then $sExclude = "" If $iFormat = -1 Or $iFormat = Default Then $iFormat = 1 If $sExclude Then ;prepare $sTExclude ;Strip leading and trailing spaces and spaces between semi colon delimiter $sTExclude = StringStripWS(StringRegExpReplace($sExclude, "\s*;\s*", ";"), 3) ;convert $sExclude to RegExp formated string $sTExclude = StringReplace($sTExclude, ".", "\.") $sTExclude = StringReplace($sTExclude, "?", ".") $sTExclude = StringReplace($sTExclude, "*", ".*?") $sTExclude = StringReplace($sTExclude, ";", "|") EndIf ;separate multi path Local $aPath = StringSplit($sPath, ';') ;separate multi filter Local $aFilter = StringSplit($sFilter, ';') For $iPCount = 1 To $aPath[0] Local $sPathItem = StringStripWS($aPath[$iPCount], 3) ;Strip leading and trailing spaces Local $sDelim = "|" ;reset $sDelim If StringRight($sPathItem, 1) <> "\" Then $sPathItem = $sPathItem & "\" ;check for trailing "\" ;return full-path or filename only ($iFlag 0,1,2 = Filename, $iFlag 4,5,6 = full path) If $iFlag > 3 Then $sDelim &= $sPathItem $TFlag = $iFlag - 4 Else $TFlag = $iFlag EndIf ;perform the search For $iFCount = 1 To $aFilter[0] Local $FilterItem = StringStripWS($aFilter[$iFCount], 3) ;Strip leading and trailing spaces If StringRegExp($FilterItem, "[\\/:<>|]") Then ContinueLoop ;Look for bad chars $hSearch = FileFindFirstFile($sPathItem & $FilterItem) If @error Then ContinueLoop Switch $TFlag Case 0 ;Files and Folders While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;optional exclude filename/folder If $sTExclude Then If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop EndIf $sFileList &= $sDelim & $sFile WEnd Case 1 ;Files Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;If StringInStr(FileGetAttrib($sPath & $sFile), "D") <> 0 Then ContinueLoop; bypass folder (ver 3.3.0.0) If @extended Then ContinueLoop ;bypass folder (for Autoit versions > 3.3.0.0) ;optional exclude filename/folder If $sTExclude Then If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop EndIf $sFileList &= $sDelim & $sFile WEnd Case 2 ;Folders Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;If StringInStr(FileGetAttrib($sPath & $sFile), "D") = 0 Then ContinueLoop; bypass file (ver 3.3.0.0) If @extended = 0 Then ContinueLoop ;bypass file (for Autoit versions > 3.3.0.0) ;optional exclude filename/folder If $sTExclude Then If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop EndIf $sFileList &= $sDelim & $sFile WEnd Case Else Return SetError(3, 3, "") EndSwitch FileClose($hSearch) Next ;--------------- ;optional do a recursive search If $bRecursiv Then $hSearch = FileFindFirstFile($sPathItem & "*.*") If Not @error Then While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;If StringInStr(FileGetAttrib($sPath & $sFile), "D") = 0 Then ContinueLoop; bypass file (ver 3.3.0.0) If @extended = 0 Then ContinueLoop ;bypass file (for Autoit versions > 3.3.0.0) ;optional exclude filename/folder If $sTExclude Then If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop EndIf ;call recursive search $sFileList &= _FileListToArrayEx2($sPathItem & $sFile, $sFilter, $iFlag, $bRecursiv, $sExclude, 0) WEnd FileClose($hSearch) EndIf EndIf Next ;$iPCount ;--------------- ;Set according return value Switch $iFormat Case 0 Return $sFileList Case 1 If $sFileList = "" Then Local $aRet[1] = [0] Return $aRet Else Return StringSplit(StringTrimLeft($sFileList, 1), "|", $iFormat) EndIf Case 2 If $sFileList = "" Then Return "" Else Return StringSplit(StringTrimLeft($sFileList, 1), "|", $iFormat) EndIf EndSwitch EndFunc ;==>_FileListToArrayEx2 Edited June 28, 2009 by BaKaMu Link to comment Share on other sites More sharing options...
Tlem Posted June 28, 2009 Author Share Posted June 28, 2009 Really great ... Just for my knowledge, I try to modified the original function to use @Extended. But even with this, it's not faster than the new one with so much function (I try it with $iFlag = 0 and $iFlag = 1 on 50000 files). Your new function seems to be 2X faster. If I compare original _FileListToArray() and a modified version that use @Extended (on v3.3.1.1) the work time of these 2 functions are similar. Just 150ms of gain with $iFlag = 0 but no gain with $iFlag = 1. So we can said that this function is obsolete. @BaKaMu In the test of your new function, I noticed that if I want exclude a directory like $hs_mig$ (who is in my Windows dir), it doesn't work. But once again, I'm really impressed by the speed of this function in spite of all its options. Now, I am impatient of the release of the final version of the new version of AutoIt. Best Regards.Thierry Link to comment Share on other sites More sharing options...
BaKaMu Posted June 28, 2009 Share Posted June 28, 2009 (edited) Dedicated to Speed-Freaks (like me): ;-) Another speed optimized version. A lot more code, but some more speed (compared to _FileListToArrayEx2 with the new DOS-Wildcard conversion). @BaKaMu In the test of your new function, I noticed that if I want exclude a directory like $hs_mig$ (who is in my Windows dir), it doesn't work.Corrected in this version (i hope so, please test). The DOS-Wildcard to RegExp conversion of $sExclude is now a little bit more complicated. (maybe some experts for StringRegExpReplace have a better solution for this) !!Edit-1!!: some time consuming requests removed (If $sTExclude ... ), gives some little speed gain if exclude is used. !!Edit-2!!: better DOS-Wildcard to RegExp conversion, gives significant more speed if exclude is used, thanks KaFu and Ascend4nt. New Version of _FileListToArrayEx expandcollapse popup; #FUNCTION# =========================================================================================== ; Name: _FileListToArrayEx3 ; Description: full compatible _FileListToArray replacement (with more speed and additional features) ; additional: multi-path, multi-filter, multi exclude-filter, recursiv search ; optional full pathname ; Syntax: _FileListToArrayEx3([$sPath = @ScriptDir, [$sFilter = "*", [$iFlag = 0, [$bRecursiv = False, [$sExclude = "", [$iFormat = 1]]]]]]) ; Parameter(s): $sPath = optional: path to generate filelist for, multi paths separated with semicolon (ex: "C:\Tmp;D:\Temp") ; if no path is given then @ScriptDir is used ; $sFilter = optional: The filter to use. (default: "*") ; multi filters separated with semicolon (ex: *.exe; *.txt will find all .exe and .txt files) ; (Search the Autoit3 manual for the word "WildCards" for details) ; $iFlag = Optional: specifies whether to return files, folders or both ; 0 = (Default) Return both files and folders ; 1 = Return files only ; 2 = Return folders only ; $iFlag + 4 = Return Filenames and/or Folders incl full Path ; $bRecursiv = optional: true: recursive search in rootdir and subdirs ; False (default): search only in rootdir ; $sExclude = optional: exclude a file/folder from the list by all or part of its name, various statements delimited with semicolon ; (ex: Unins* will remove all files/folders that start with Unins) ; $iFormat = optional: return format ; 0 = String ( "|" delimited) ; 1 = (default) one-dimensional array, array[0] = number of files\folders returned ; 2 = one-dimensional array, 0-based ; Requirement(s): none ; Return Value(s): on success: string or array (dependent on $iFormat) ; Author(s): bernd670, Tlem, Spiff59, Zedna, KaFu, SmOke_N, GEOSoft, Ascend4nt, BaKaMu ; ==================================================================================================== Func _FileListToArrayEx3($sPath = @ScriptDir, $sFilter = "*", $iFlag = 0, $bRecursiv = False, $sExclude = "", $iFormat = 1) Local $hSearch, $iPCount, $iFCount, $sFile, $TFlag = 0, $sFileList = "", $sTExclude = "" If $sPath = -1 Or $sPath = Default Then $sPath = @ScriptDir If $sFilter = -1 Or $sFilter = Default Then $sFilter = "*" If $iFlag = -1 Or $iFlag = Default Then $iFlag = 0 If $bRecursiv = Default Then $bRecursiv = False If $sExclude = -1 Or $sExclude = Default Then $sExclude = "" If $iFormat = -1 Or $iFormat = Default Then $iFormat = 1 ;separate multi path Local $aPath = StringSplit($sPath, ';') ;separate multi filter Local $aFilter = StringSplit($sFilter, ';') If $sExclude Then ;prepare $sTExclude ;Strip leading and trailing spaces and spaces between semi colon delimiter $sTExclude = StringStripWS(StringRegExpReplace($sExclude, "\s*;\s*", ";"), 3) ;convert $sExclude to fit StringRegExp (not perfect but useable) $sTExclude = StringRegExpReplace($sTExclude, '([\Q\.+[^]$(){}=!\E])', '\\$1') ;thanks KaFu and Ascend4nt $sTExclude = StringReplace($sTExclude, "?", ".") $sTExclude = StringReplace($sTExclude, "*", ".*?") $sTExclude = StringReplace($sTExclude, ";", "|") For $iPCount = 1 To $aPath[0] Local $sPathItem = StringStripWS($aPath[$iPCount], 3) ;Strip leading and trailing spaces Local $sDelim = "|" ;reset $sDelim If StringRight($sPathItem, 1) <> "\" Then $sPathItem = $sPathItem & "\" ;check for trailing "\" ;return full-path or filename only ($iFlag 0,1,2 = Filename, $iFlag 4,5,6 = full path) If $iFlag > 3 Then $sDelim &= $sPathItem $TFlag = $iFlag - 4 Else $TFlag = $iFlag EndIf ;perform the search For $iFCount = 1 To $aFilter[0] Local $FilterItem = StringStripWS($aFilter[$iFCount], 3) ;Strip leading and trailing spaces If StringRegExp($FilterItem, "[\\/:<>|]") Then ContinueLoop ;Look for bad chars $hSearch = FileFindFirstFile($sPathItem & $FilterItem) If @error Then ContinueLoop Switch $TFlag Case 0 ;Files and Folders While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;check for exclude filename/folder If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop $sFileList &= $sDelim & $sFile WEnd Case 1 ;Files Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;If StringInStr(FileGetAttrib($sPath & $sFile), "D") <> 0 Then ContinueLoop; bypass folder (ver 3.3.0.0) If @extended Then ContinueLoop ;bypass folder (for Autoit versions > 3.3.0.0) ;check for exclude filename/folder If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop $sFileList &= $sDelim & $sFile WEnd Case 2 ;Folders Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;If StringInStr(FileGetAttrib($sPath & $sFile), "D") = 0 Then ContinueLoop; bypass file (ver 3.3.0.0) If @extended = 0 Then ContinueLoop ;bypass file (for Autoit versions > 3.3.0.0) ;check for exclude filename/folder If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop $sFileList &= $sDelim & $sFile WEnd Case Else Return SetError(3, 3, "") EndSwitch FileClose($hSearch) Next ;--------------- ;optional do a recursive search If $bRecursiv Then $hSearch = FileFindFirstFile($sPathItem & "*.*") If Not @error Then While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;If StringInStr(FileGetAttrib($sPath & $sFile), "D") = 0 Then ContinueLoop; bypass file (ver 3.3.0.0) If @extended = 0 Then ContinueLoop ;bypass file (for Autoit versions > 3.3.0.0) ;check for exclude folder If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop ;call recursive search $sFileList &= _FileListToArrayEx3($sPathItem & $sFile, $sFilter, $iFlag, $bRecursiv, $sExclude, 0) WEnd FileClose($hSearch) EndIf EndIf Next ;$iPCount Else ;If Not $sExclude For $iPCount = 1 To $aPath[0] Local $sPathItem = StringStripWS($aPath[$iPCount], 3) ;Strip leading and trailing spaces Local $sDelim = "|" ;reset $sDelim If StringRight($sPathItem, 1) <> "\" Then $sPathItem = $sPathItem & "\" ;check for trailing "\" ;return full-path or filename only ($iFlag 0,1,2 = Filename, $iFlag 4,5,6 = full path) If $iFlag > 3 Then $sDelim &= $sPathItem $TFlag = $iFlag - 4 Else $TFlag = $iFlag EndIf ;perform the search For $iFCount = 1 To $aFilter[0] Local $FilterItem = StringStripWS($aFilter[$iFCount], 3) ;Strip leading and trailing spaces If StringRegExp($FilterItem, "[\\/:<>|]") Then ContinueLoop ;Look for bad chars $hSearch = FileFindFirstFile($sPathItem & $FilterItem) If @error Then ContinueLoop Switch $TFlag Case 0 ;Files and Folders While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop $sFileList &= $sDelim & $sFile WEnd Case 1 ;Files Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;If StringInStr(FileGetAttrib($sPath & $sFile), "D") <> 0 Then ContinueLoop; bypass folder (ver 3.3.0.0) If @extended Then ContinueLoop ;bypass folder (for Autoit versions > 3.3.0.0) $sFileList &= $sDelim & $sFile WEnd Case 2 ;Folders Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;If StringInStr(FileGetAttrib($sPath & $sFile), "D") = 0 Then ContinueLoop; bypass file (ver 3.3.0.0) If @extended = 0 Then ContinueLoop ;bypass file (for Autoit versions > 3.3.0.0) $sFileList &= $sDelim & $sFile WEnd Case Else Return SetError(3, 3, "") EndSwitch FileClose($hSearch) Next ;--------------- ;optional do a recursive search If $bRecursiv Then $hSearch = FileFindFirstFile($sPathItem & "*.*") If Not @error Then While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;If StringInStr(FileGetAttrib($sPath & $sFile), "D") = 0 Then ContinueLoop; bypass file (ver 3.3.0.0) If @extended = 0 Then ContinueLoop ;bypass file (for Autoit versions > 3.3.0.0) ;call recursive search $sFileList &= _FileListToArrayEx3($sPathItem & $sFile, $sFilter, $iFlag, $bRecursiv, $sExclude, 0) WEnd FileClose($hSearch) EndIf EndIf Next ;$iPCount EndIf ;If $sExclude ;--------------- ;Set according return value Switch $iFormat Case 0 Return $sFileList Case 1 If $sFileList = "" Then Local $aRet[1] = [0] Return $aRet Else Return StringSplit(StringTrimLeft($sFileList, 1), "|", $iFormat) EndIf Case 2 If $sFileList = "" Then Return "" Else Return StringSplit(StringTrimLeft($sFileList, 1), "|", $iFormat) EndIf EndSwitch EndFunc ;==>_FileListToArrayEx3 Edited June 28, 2009 by BaKaMu Link to comment Share on other sites More sharing options...
BaKaMu Posted June 28, 2009 Share Posted June 28, 2009 New Version of _FileListToArrayExEdited Post #66 Link to comment Share on other sites More sharing options...
KaFu Posted June 28, 2009 Share Posted June 28, 2009 The DOS-Wildcard to RegExp conversion of $sExclude is now a little bit more complicated.In SMF I utilize this function with good resultshttp://www.autoitscript.com/forum/index.php?showtopic=90846 OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
Zedna Posted June 28, 2009 Share Posted June 28, 2009 (edited) I think the debate is more simplicity versus complexity.I've nothing against complexity, if it is useful, but all the new parameters open up a lot of combinations of interaction between $iFlag, $sFilter, and any specified exclude strings. I mentioned a few of the possibilities in my last post. I would think that how these parms all work together would need to be determined, and documented.I don't know what are plans of Autoit's developers but maybe _FileListToArray() can remain as it is (only optimized without new parametres)and new robust version _FileListToArrayEx() ca be added with all possible functionality like excludes etc. Edited June 28, 2009 by Zedna Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
BaKaMu Posted June 28, 2009 Share Posted June 28, 2009 New Version of _FileListToArrayExEdited Post #66 again Link to comment Share on other sites More sharing options...
jpm Posted June 28, 2009 Share Posted June 28, 2009 For me as soon the extended version is ready without breaking the previous release/beta version I will incorporate it in the standard UDF please uppdate the doc at the same time Just PM me the function an its doc Link to comment Share on other sites More sharing options...
Spiff59 Posted June 28, 2009 Share Posted June 28, 2009 (edited) I don't know what are plans of Autoit's developers but maybe _FileListToArray() can remain as it is (only optimized without new parametres) and new robust version _FileListToArrayEx() ca be added with all possible functionality like excludes etc.Two versions, FileListToArray() and FileListToArrayEx() sounds like a good idea to me. If the Ex version is to have all the bells-and-whistles, then there's something missing, in my opinion. Like a DOS search, if you start from a certain directory and include subdirectories it will return partial paths, or referential paths, or relative paths, whatever it should be called. For instance, if you search the Autoit folder for *.exe, with recursion on, one of the elements returned would be "Aut2Exe\Aut2.exe". The path relative to $sPath. Implementing it took only a few lines of code, but brought up another concern. Variable names are supposed to be descriptive, self-documenting, $iFLag doesn't pass that test. It had become a dual-use flag, setting both "what is being searched" and "the format of what is returned". I don't really care what names are settled upon, but in the version below (based on the latest post #66), I've split $iFlag into 2 variables: $SrchType = What to search for: 0 = Files and Folder, 1 = Files Only, 2 = Folders Only $PathType = The format of returned elements: 0 = file/folder name only, 1 = relative path, 2 = full path What do you think? expandcollapse popup#include<array.au3> ;Testing parameters Dim $Repeat = 1 Dim $SearchPath = "C:\Program Files\Autoit3\AutoitX" Dim $Pattern = "*" Dim $SrchType = 1; What to search for: 0 = Files and Folders, 1 = Files Only, 2 = Folders Only Dim $PathType = 1; Format of returned string: 0 = file/folder name only, 1 = partial/referential path, 2 = full path Dim $Exclude = "" Dim $Recursiv = True $aRet = _FileListToArrayEx3($SearchPath, $Pattern, $SrchType, $PathType, $Recursiv, $Exclude, 1) _ArrayDisplay($aRet) Exit ; #FUNCTION# =========================================================================================== ; Name: _FileListToArrayEx3 ; Description: full compatible _FileListToArray replacement (with more speed and additional features) ; additional: multi-path, multi-filter, multi exclude-filter, recursiv search ; optional full pathname ; Syntax: _FileListToArrayEx3([$sPath = @ScriptDir, [$sFilter = "*", [$iSrchType, [$bRecursiv = False, [$sExclude = "", [$iFormat = 1]]]]]]) ; Parameter(s): $sPath = optional: path to generate filelist for, multi paths separated with semicolon (ex: "C:\Tmp;D:\Temp") ; if no path is given then @ScriptDir is used ; $sFilter = optional: The filter to use. (default: "*") ; multi filters separated with semicolon (ex: *.exe; *.txt will find all .exe and .txt files) ; (Search the Autoit3 manual for the word "WildCards" for details) ; $iSrchType = Optional: specifies whether to return files, folders or both ; 0 = (Default) Return both files and folders ; 1 = Return files only ; 2 = Return folders only ; $iSrchType + 4 = Return Filenames and/or Folders incl full Path ; $bRecursiv = optional: true: recursive search in rootdir and subdirs ; False (default): search only in rootdir ; $sExclude = optional: exclude a file/folder from the list by all or part of its name, various statements delimited with semicolon ; (ex: Unins* will remove all files/folders that start with Unins) ; $iFormat = optional: return format ; 0 = String ( "|" delimited) ; 1 = (default) one-dimensional array, array[0] = number of files\folders returned ; 2 = one-dimensional array, 0-based ; Requirement(s): none ; Return Value(s): on success: string or array (dependent on $iFormat) ; Author(s): bernd670, Tlem, Spiff59, Zedna, KaFu, SmOke_N, GEOSoft, Ascend4nt, BaKaMu ; ==================================================================================================== Func _FileListToArrayEx3($sPath = @ScriptDir, $sFilter = "*", $iSrchType = 0, $iPathType = 0, $bRecursiv = False, $sExclude = "", $iFormat = 1, $wrk = "") Local $hSearch, $iPCount, $iFCount, $sFile, $SrchType = 0, $sFileList = "", $sTExclude = "", $wrk2 If $sPath = -1 Or $sPath = Default Then $sPath = @ScriptDir If $sFilter = -1 Or $sFilter = Default Then $sFilter = "*" If $iSrchType = -1 Or $iSrchType = Default Then $iSrchType = 0 If $bRecursiv = Default Then $bRecursiv = False If $sExclude = -1 Or $sExclude = Default Then $sExclude = "" If $iFormat = -1 Or $iFormat = Default Then $iFormat = 1 ;separate multi path Local $aPath = StringSplit($sPath, ';') ;separate multi filter Local $aFilter = StringSplit($sFilter, ';') If $sExclude Then ;prepare $sTExclude ;Strip leading and trailing spaces and spaces between semi colon delimiter $sTExclude = StringStripWS(StringRegExpReplace($sExclude, "\s*;\s*", ";"), 3) ;convert $sExclude to fit StringRegExp (not perfect but useable) $sTExclude = StringRegExpReplace($sTExclude, '([\Q\.+[^]$(){}=!\E])', '\\$1');thanks KaFu and Ascend4nt $sTExclude = StringReplace($sTExclude, "?", ".") $sTExclude = StringReplace($sTExclude, "*", ".*?") $sTExclude = StringReplace($sTExclude, ";", "|") For $iPCount = 1 To $aPath[0] Local $sPathItem = StringStripWS($aPath[$iPCount], 3);Strip leading and trailing spaces Local $sDelim = "|";reset $sDelim If StringRight($sPathItem, 1) <> "\" Then $sPathItem = $sPathItem & "\";check for trailing "\" ;return full-path If $iPathType = 2 Then $sDelim &= $sPathItem ;perform the search For $iFCount = 1 To $aFilter[0] Local $FilterItem = StringStripWS($aFilter[$iFCount], 3);Strip leading and trailing spaces If StringRegExp($FilterItem, "[\\/:<>|]") Then ContinueLoop;Look for bad chars $hSearch = FileFindFirstFile($sPathItem & $FilterItem) If @error Then ContinueLoop Switch $SrchType Case 0;Files and Folders While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;check for exclude filename/folder If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop $sFileList &= $sDelim & $wrk & $sFile WEnd Case 1;Files Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop If @extended Then ContinueLoop;bypass folder (for Autoit versions > 3.3.0.0) ;check for exclude filename/folder If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop $sFileList &= $sDelim & $wrk & $sFile WEnd Case 2;Folders Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop If @extended = 0 Then ContinueLoop;bypass file (for Autoit versions > 3.3.0.0) ;check for exclude filename/folder If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop $sFileList &= $sDelim & $wrk & $sFile WEnd Case Else Return SetError(3, 3, "") EndSwitch FileClose($hSearch) Next ;--------------- ;optional do a recursive search If $bRecursiv Then $hSearch = FileFindFirstFile($sPathItem & "*.*") If Not @error Then While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop If @extended = 0 Then ContinueLoop;bypass file (for Autoit versions > 3.3.0.0) ;check for exclude folder If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop ;call recursive search $sFileList &= _FileListToArrayEx3($sPathItem & $sFile, $sFilter, $iSrchType, $bRecursiv, $sExclude, 0) WEnd FileClose($hSearch) EndIf EndIf Next;$iPCount Else;If Not $sExclude For $iPCount = 1 To $aPath[0] Local $sPathItem = StringStripWS($aPath[$iPCount], 3);Strip leading and trailing spaces Local $sDelim = "|";reset $sDelim If StringRight($sPathItem, 1) <> "\" Then $sPathItem = $sPathItem & "\";check for trailing "\" ;return full-path If $iPathType = 2 Then $sDelim &= $sPathItem ;perform the search For $iFCount = 1 To $aFilter[0] Local $FilterItem = StringStripWS($aFilter[$iFCount], 3);Strip leading and trailing spaces If StringRegExp($FilterItem, "[\\/:<>|]") Then ContinueLoop;Look for bad chars $hSearch = FileFindFirstFile($sPathItem & $FilterItem) If @error Then ContinueLoop Switch $SrchType Case 0;Files and Folders While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop $sFileList &= $sDelim & $wrk & $sFile WEnd Case 1;Files Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop If @extended Then ContinueLoop;bypass folder (for Autoit versions > 3.3.0.0) $sFileList &= $sDelim & $wrk & $sFile WEnd Case 2;Folders Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop If @extended = 0 Then ContinueLoop;bypass file (for Autoit versions > 3.3.0.0) $sFileList &= $sDelim & $wrk & $sFile WEnd Case Else Return SetError(3, 3, "") EndSwitch FileClose($hSearch) Next ;--------------- ;optional do a recursive search If $bRecursiv Then $hSearch = FileFindFirstFile($sPathItem & "*.*") If Not @error Then While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop If @extended = 0 Then ContinueLoop;bypass file (for Autoit versions > 3.3.0.0) ;call recursive search If $PathType = 1 Then $wrk2 = $wrk & $sFile & "\" $sFileList &= _FileListToArrayEx3($sPathItem & $sFile, $sFilter, $iSrchType, $iPathType, $bRecursiv, $sExclude, 0, $wrk2) WEnd FileClose($hSearch) EndIf EndIf Next;$iPCount EndIf;If $sExclude ;--------------- ;Set according return value Switch $iFormat Case 0 Return $sFileList Case 1 If $sFileList = "" Then Local $aRet[1] = [0] Return $aRet Else Return StringSplit(StringTrimLeft($sFileList, 1), "|", $iFormat) EndIf Case 2 If $sFileList = "" Then Return "" Else Return StringSplit(StringTrimLeft($sFileList, 1), "|", $iFormat) EndIf EndSwitch EndFunc ;==>_FileListToArrayEx3 Edited June 28, 2009 by Spiff59 Link to comment Share on other sites More sharing options...
BaKaMu Posted June 28, 2009 Share Posted June 28, 2009 (edited) If the Ex version is to have all the bells-and-whistles, then there's something missing, in my opinion. Like a DOS search, if you start from a certain directory and include subdirectories it will return partial paths, or referential paths, or relative paths, whatever it should be called. For instance, if you search the Autoit folder for *.exe, with recursion on, one of the elements returned would be "Aut2Exe\Aut2.exe". The path relative to $sPath. What do you think?To spend a extra flag for the type of returned path (none, relative, full) is a additional feature for _FileListToArrayEx. (even though i don't know a really useful application for relative pathes, but maybe good for others) There have been some bugs in your implementation, so i have corrected this. (and have made some clarification for variable names) Your implementation also decreases the speed a little bit (but not noticeable) Most important is the fact, that the first 3 variables ($sPath, $sFilter, $iSearchType) are remaining the same, so the compatibility to _FileListToArray is given. So it maybe advisable to name $iSearchType back to $iFlag, cause in _FileListToArray it is called $iFlag (to not confuse same user, but this is discussible) The corrected code of your implementation. expandcollapse popup; #FUNCTION# =========================================================================================== ; Name: _FileListToArrayEx4 ; Description: full compatible _FileListToArray replacement (with more speed and additional features) ; additional: multi-path, multi-filter, multi exclude-filter, recursiv search ; optional full pathname ; Syntax: _FileListToArrayEx4([$sPath = @ScriptDir, [$sFilter = "*", [$iSearchType, [$bRecursiv = False, [$sExclude = "", [$iRetFormat = 1]]]]]]) ; Parameter(s): $sPath = optional: path to generate filelist for, multi paths separated with semicolon (ex: "C:\Tmp;D:\Temp") ; if no path is given then @ScriptDir is used ; $sFilter = optional: The filter to use. (default: "*") ; multi filters separated with semicolon (ex: *.exe; *.txt will find all .exe and .txt files) ; (Search the Autoit3 manual for the word "WildCards" for details) ; $iSearchType = What to search for: 0 = Files and Folder, 1 = Files Only, 2 = Folders Only ; $iPathType = The format of returned elements: 0 = file/folder name only, 1 = relative path, 2 = full path ; $bRecursiv = optional: true: recursive search in rootdir and subdirs ; False (default): search only in rootdir ; $sExclude = optional: exclude a file/folder from the list by all or part of its name, various statements delimited with semicolon ; (ex: Unins* will remove all files/folders that start with Unins) ; $iRetFormat = optional: return format ; 0 = String ( "|" delimited) ; 1 = (default) one-dimensional array, array[0] = number of files\folders returned ; 2 = one-dimensional array, 0-based ; $sWorkPath = internal use only (do not assign a value) ; Requirement(s): none ; Return Value(s): on success: string or array (dependent on $iRetFormat) ; Author(s): bernd670, Tlem, Spiff59, Zedna, KaFu, SmOke_N, GEOSoft, Ascend4nt, BaKaMu ; ==================================================================================================== Func _FileListToArrayEx4($sPath = @ScriptDir, $sFilter = "*", $iSearchType = 0, $iPathType = 0, $bRecursiv = False, $sExclude = "", $iRetFormat = 1, $sWorkPath = "") Local $hSearch, $iPCount, $iFCount, $sFile, $sFileList = "", $sTExclude = "", $sTWorkPath If $sPath = -1 Or $sPath = Default Then $sPath = @ScriptDir If $sFilter = -1 Or $sFilter = Default Then $sFilter = "*" If $iSearchType = -1 Or $iSearchType = Default Then $iSearchType = 0 If $iPathType = -1 Or $iPathType = Default Then $iPathType = 0 If $bRecursiv = Default Then $bRecursiv = False If $sExclude = -1 Or $sExclude = Default Then $sExclude = "" If $iRetFormat = -1 Or $iRetFormat = Default Then $iRetFormat = 1 ;separate multi path Local $aPath = StringSplit($sPath, ';') ;separate multi filter Local $aFilter = StringSplit($sFilter, ';') If $sExclude Then ;prepare $sTExclude ;Strip leading and trailing spaces and spaces between semi colon delimiter $sTExclude = StringStripWS(StringRegExpReplace($sExclude, "\s*;\s*", ";"), 3) ;convert $sExclude to fit StringRegExp (not perfect but useable) $sTExclude = StringRegExpReplace($sTExclude, '([\Q\.+[^]$(){}=!\E])', '\\$1') ;thanks KaFu and Ascend4nt $sTExclude = StringReplace($sTExclude, "?", ".") $sTExclude = StringReplace($sTExclude, "*", ".*?") $sTExclude = StringReplace($sTExclude, ";", "|") For $iPCount = 1 To $aPath[0] Local $sPathItem = StringStripWS($aPath[$iPCount], 3) ;Strip leading and trailing spaces Local $sDelim = "|" ;reset $sDelim If StringRight($sPathItem, 1) <> "\" Then $sPathItem = $sPathItem & "\" ;check for trailing "\" ;return full-path If $iPathType = 2 Then $sDelim &= $sPathItem ;perform the search For $iFCount = 1 To $aFilter[0] Local $FilterItem = StringStripWS($aFilter[$iFCount], 3) ;Strip leading and trailing spaces If StringRegExp($FilterItem, "[\\/:<>|]") Then ContinueLoop ;Look for bad chars $hSearch = FileFindFirstFile($sPathItem & $FilterItem) If @error Then ContinueLoop Switch $iSearchType Case 0 ;Files and Folders While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;check for exclude filename/folder If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop $sFileList &= $sDelim & $sWorkPath & $sFile WEnd Case 1 ;Files Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop If @extended Then ContinueLoop ;bypass folder (for Autoit versions > 3.3.0.0) ;check for exclude filename/folder If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop $sFileList &= $sDelim & $sWorkPath & $sFile WEnd Case 2 ;Folders Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop If @extended = 0 Then ContinueLoop ;bypass file (for Autoit versions > 3.3.0.0) ;check for exclude filename/folder If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop $sFileList &= $sDelim & $sWorkPath & $sFile WEnd Case Else Return SetError(3, 3, "") EndSwitch FileClose($hSearch) Next ;--------------- ;optional do a recursive search If $bRecursiv Then $hSearch = FileFindFirstFile($sPathItem & "*.*") If Not @error Then While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop If @extended = 0 Then ContinueLoop ;bypass file (for Autoit versions > 3.3.0.0) ;check for exclude folder If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop ;call recursive search If $iPathType = 1 Then $sTWorkPath = $sWorkPath & $sFile & "\" $sFileList &= _FileListToArrayEx4($sPathItem & $sFile, $sFilter, $iSearchType, $iPathType, $bRecursiv, $sExclude, 0, $sTWorkPath) WEnd FileClose($hSearch) EndIf EndIf Next ;$iPCount Else ;If Not $sExclude For $iPCount = 1 To $aPath[0] Local $sPathItem = StringStripWS($aPath[$iPCount], 3) ;Strip leading and trailing spaces Local $sDelim = "|" ;reset $sDelim If StringRight($sPathItem, 1) <> "\" Then $sPathItem = $sPathItem & "\" ;check for trailing "\" ;return full-path If $iPathType = 2 Then $sDelim &= $sPathItem ;perform the search For $iFCount = 1 To $aFilter[0] Local $FilterItem = StringStripWS($aFilter[$iFCount], 3) ;Strip leading and trailing spaces If StringRegExp($FilterItem, "[\\/:<>|]") Then ContinueLoop ;Look for bad chars $hSearch = FileFindFirstFile($sPathItem & $FilterItem) If @error Then ContinueLoop Switch $iSearchType Case 0 ;Files and Folders While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop $sFileList &= $sDelim & $sWorkPath & $sFile WEnd Case 1 ;Files Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop If @extended Then ContinueLoop ;bypass folder (for Autoit versions > 3.3.0.0) $sFileList &= $sDelim & $sWorkPath & $sFile WEnd Case 2 ;Folders Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop If @extended = 0 Then ContinueLoop ;bypass file (for Autoit versions > 3.3.0.0) $sFileList &= $sDelim & $sWorkPath & $sFile WEnd Case Else Return SetError(3, 3, "") EndSwitch FileClose($hSearch) Next ;--------------- ;optional do a recursive search If $bRecursiv Then $hSearch = FileFindFirstFile($sPathItem & "*.*") If Not @error Then While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop If @extended = 0 Then ContinueLoop ;bypass file (for Autoit versions > 3.3.0.0) ;call recursive search If $iPathType = 1 Then $sTWorkPath = $sWorkPath & $sFile & "\" $sFileList &= _FileListToArrayEx4($sPathItem & $sFile, $sFilter, $iSearchType, $iPathType, $bRecursiv, $sExclude, 0, $sTWorkPath) WEnd FileClose($hSearch) EndIf EndIf Next ;$iPCount EndIf ;If $sExclude ;--------------- ;Set according return value Switch $iRetFormat Case 0 Return $sFileList Case 1 If $sFileList = "" Then Local $aRet[1] = [0] Return $aRet Else Return StringSplit(StringTrimLeft($sFileList, 1), "|", $iRetFormat) EndIf Case 2 If $sFileList = "" Then Return "" Else Return StringSplit(StringTrimLeft($sFileList, 1), "|", $iRetFormat) EndIf EndSwitch EndFunc ;==>_FileListToArrayEx4 Edited June 28, 2009 by BaKaMu Link to comment Share on other sites More sharing options...
Spiff59 Posted June 28, 2009 Share Posted June 28, 2009 (edited) There have been some bugs in your implementation,It looks the same to me... just curious... what were the bugs?Since I was just floating the idea, I hadn't bothered to update the description in the function header.If we're going to submit both a new FileListToArray and a FileListToArryaEx together, then having the internal parameter names match is not a problem, and changing them wouldn't be a script-breaker. It's nitpicking really, $iFlag has no useful meaning as far as self-documentation, but if it stays with that name I wouldn't lose sleep any over it.Edit: Oh, I'd forgotten, there are two of everything now. I had only updated one of the two recursion loops. Edited June 28, 2009 by Spiff59 Link to comment Share on other sites More sharing options...
BaKaMu Posted June 28, 2009 Share Posted June 28, 2009 (edited) It looks the same to me... just curious... what were the bugs?Since I was just floating the idea, I hadn't bothered to update the description in the function header.If we're going to submit both a new FileListToArray and a FileListToArryaEx together, then having the internal parameter names match is not a problem, and changing them wouldn't be a script-breaker. It's nitpicking really, $iFlag has no useful meaning as far as self-documentation, but if it stays with that name I wouldn't lose sleep any over it.Edit: Oh, I'd forgotten, there are two of everything now. I had only updated one of the two recursion loops.this bug you have seen,and you have $PathType in line 194 (should be $iPathType),and you have $SrchType in line 85, 156 (should be $iSrchType)and then you can remove $SrchType from local declarationYou got no error, cause these variables are declared outside of function (perfidiously error) :-) Edited June 28, 2009 by BaKaMu Link to comment Share on other sites More sharing options...
Spiff59 Posted June 28, 2009 Share Posted June 28, 2009 (edited) and you have $PathType in line 194 (should be $iPathType),and you have $SrchType in line 85, 156 (should be $iSrchType)Ah, right you are. I trashed some stuff doing global replaces and then manually patched up the variable names. I wasn't very thorough So... Error handling and the documentation about "Return value(s)" isn't finished.The exisiting FileListToArray() claims to return @error = 4 for a not-find, but actually only works if $iFlag = 0, otherwise it is returning a one-element array with that element empty. There is a 1-line fix for that to make it return @error = 4 in all cases.In the new routine, the option for multiple pathnames and multiple filters negates the possibility of the @error = 1 and @error = 2 returns of the original routine. @error = 4 is also gone, and depending on the $iFormat flag either a null string, or a one-based array with a value of zero, is returned. Maybe the last @error should be trashed, the one for invalid $iFlag, just make the code "Case 1: Files only, Case 2: Folders only, Case Else: Files and Folders"? This handling of @error is a script-breaker and if there is an intention of this replacing, or being baclward-compatible with the exisiting FileListToArray() there's a problem.But this version does everything but butter your toast, and is still faster than the original. Do we want to (request to) retain FileListToArray() using the new fast basic version with the @error handling intact? And then have the FileListToArrayEx super-function that has different error processing?typo Edited June 28, 2009 by Spiff59 Link to comment Share on other sites More sharing options...
Tlem Posted June 28, 2009 Author Share Posted June 28, 2009 (edited) To my opinion, FileListToArrayEx() is a new function. The original function must has to remain such which. But it can be improved by few modification like the use of @Extended and my first suggestion to not use the array in the function but strings, and the return of the full path. The line for Windows 98 is not any more right to be because AutoIt does not support any more Win98 So I suggest the optimized version by Spiff59. This version is really more faster than the original (2X), but it's the same. expandcollapse popupFunc _FileListToArray($sPath, $sFilter = "*", $iFlag = 0) Local $hSearch, $sFile, $sFileList, $sDelim = "|" If Not FileExists($sPath) Then Return SetError(1, 1, "") If StringRegexp($sFilter, "[\\/:<>|]") Or (Not StringStripWS($sFilter, 8)) Then Return SetError(2, 2, "") If StringRight($sPath, 1) <> "\" Then $sPath &= "\" $hSearch = FileFindFirstFile($sPath & $sFilter) If $hSearch = -1 Then Return SetError(4, 4, "") If $iFlag > 3 Then $sDelim &= $sPath $iflag -= 4 EndIf Switch $iFlag Case 0; Files and Folders While 1 $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop $sFileList &= $sDelim & $sFile WEnd Case 1; Files Only While 1 $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop If @extended Then ContinueLoop; bypass folder $sFileList &= $sDelim & $sFile WEnd If Not $sFileList Then Return SetError(4, 4, "") Case 2; Folders Only While 1 $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop If @extended = 0 Then ContinueLoop; bypass file $sFileList &= $sDelim & $sFile WEnd If Not $sFileList Then Return SetError(4, 4, "") Case Else Return SetError(3, 3, "") EndSwitch FileClose($hSearch) Return StringSplit(StringTrimLeft($sFileList, 1), "|") EndFunc;==>_FileListToArray What do you think about that jpm ? Edited June 29, 2009 by Tlem Best Regards.Thierry Link to comment Share on other sites More sharing options...
Spiff59 Posted June 28, 2009 Share Posted June 28, 2009 The line with the "Win98" reference removed a trailing slash, but then a later line added it back. I think it's preferential that the slash be present? And the bug regarding not returning @error = 4 when no files/folders are found should be addressed. I think the 3 extra lines (1 for the slash, 2 for the @error bug) in the example in post #63 are desirable? Link to comment Share on other sites More sharing options...
Tlem Posted June 29, 2009 Author Share Posted June 29, 2009 Code edited. Best Regards.Thierry Link to comment Share on other sites More sharing options...
BaKaMu Posted June 29, 2009 Share Posted June 29, 2009 So... Error handling and the documentation about "Return value(s)" isn't finished. The exisiting FileListToArray() claims to return @error = 4 for a not-find, but actually only works if $iFlag = 0, otherwise it is returning a one-element array with that element empty. There is a 1-line fix for that to make it return @error = 4 in all cases. In the new routine, the option for multiple pathnames and multiple filters negates the possibility of the @error = 1 and @error = 2 returns of the original routine. @error = 4 is also gone, and depending on the $iFormat flag either a null string, or a one-based array with a value of zero, is returned. Maybe the last @error should be trashed, the one for invalid $iFlag, just make the code "Case 1: Files only, Case 2: Folders only, Case Else: Files and Folders"? This handling of @error is a script-breaker and if there is an intention of this replacing, or being backward-compatible with the exisiting FileListToArray() there's a problem.Some thoughts about return values for _FileListToArrayEx: Return values depends on $Format or $RetFormat (newest version) flag Case 0 : if something found returns delimited string if nothing found returns empty string Case 1 : if something found returns one-dimensional array, array[0] = number of files\folders returned if nothing found returns one-dimensional array, array[0] = 0 Case 2 : if something found returns one-dimensional array, 0-based if nothing found returns one-dimensional array, 0-based with 0 elements, changed now to $aRet[0] (is this practical ??) ---------- Some thought about error handling for _FileListToArrayEx: My opinion is that an error should occur if some parameters are invalid. In all other situation: garbage in -> no result Version _FileListToArrayEx3: - $sPath: If a path don't exists there should be an error. But if there are multi path then there might be the situation that the first path don't exist and the second one exists Is this now an error (and on error you have to stop the routine) or not? I for me decided that this situation is not an error, simply there is no result for the non existing path. (so i removed the error handling for this situation) - $sFilter: same deliberations as for $sPath - $iFlag : if $iFlag <> 0,1,2 4,5,6 there should be an error , Return SetError(3, 3, "") - $bRecursiv: there could be nothing wrong, either it's true or not - $sExclude: i don't see any situation where an problem could occur (maybe i am wrong) - $iRetFormat: if $iRetFormat <> 0,1,2 there should be an error , i have now implemented Return SetError(4, 4, "") Version _FileListToArrayEx4: - $SearchType: if $SearchType <> 0,1,2 there should be an error , Return SetError(3, 3, "") - $PathType: if $PathType <> 0,1,2 there should be an error , Return SetError(3, 3, "") (should be implemented) - $sWorkPath: only internal use, no error checking necessary So what do you think about that (Uh, that was the longest text i ever wrote in this forum) :-) Improved Version of _FileListToArray3 expandcollapse popup; #FUNCTION# =========================================================================================== ; Name: _FileListToArrayEx3 ; Description: full compatible _FileListToArray replacement (with more speed and additional features) ; additional: multi-path, multi-filter, multi exclude-filter, recursive search ; optional full pathname ; Syntax: _FileListToArrayEx3([$sPath = @ScriptDir, [$sFilter = "*", [$iFlag = 0, [$bRecursiv = False, [$sExclude = "", [$iRetFormat = 1]]]]]]) ; Parameter(s): $sPath = optional: path to generate filelist for, multi paths separated with semicolon (ex: "C:\Tmp;D:\Temp") ; if no path is given then @ScriptDir is used ; $sFilter = optional: The filter to use. (default: "*") ; multi filters separated with semicolon (ex: *.exe; *.txt will find all .exe and .txt files) ; (Search the Autoit3 manual for the word "WildCards" for details) ; $iFlag = Optional: specifies whether to return files, folders or both ; 0 = (Default) Return both files and folders ; 1 = Return files only ; 2 = Return folders only ; $iFlag + 4 = Return Filenames and/or Folders incl full Path ; $bRecursiv = optional: true: recursive search in rootdir and subdirs ; False (default): search only in rootdir ; $sExclude = optional: exclude a file/folder from the list by all or part of its name, various statements delimited with semicolon ; (ex: Unins* will remove all files/folders that start with Unins) ; $iRetFormat = optional: return format ; 0 = String ( "|" delimited) ; 1 = (default) one-dimensional array, array[0] = number of files\folders returned ; 2 = one-dimensional array, 0-based ; Requirement(s): none ; Return Value(s): on success: string or array (dependent on $iRetFormat) ; Author(s): bernd670, Tlem, Spiff59, Zedna, KaFu, SmOke_N, GEOSoft, Ascend4nt, BaKaMu ; ==================================================================================================== Func _FileListToArrayEx3($sPath = @ScriptDir, $sFilter = "*", $iFlag = 0, $bRecursiv = False, $sExclude = "", $iRetFormat = 1) Local $hSearch, $iPCount, $iFCount, $sFile, $TFlag = 0, $sFileList = "", $sTExclude = "" If $sPath = -1 Or $sPath = Default Then $sPath = @ScriptDir If $sFilter = -1 Or $sFilter = Default Then $sFilter = "*" If $iFlag = -1 Or $iFlag = Default Then $iFlag = 0 If $bRecursiv = Default Then $bRecursiv = False If $sExclude = -1 Or $sExclude = Default Then $sExclude = "" If $iRetFormat = -1 Or $iRetFormat = Default Then $iRetFormat = 1 ;separate multi path Local $aPath = StringSplit($sPath, ';') ;separate multi filter Local $aFilter = StringSplit($sFilter, ';') If $sExclude Then ;prepare $sTExclude ;Strip leading and trailing spaces and spaces between semi colon delimiter $sTExclude = StringStripWS(StringRegExpReplace($sExclude, "\s*;\s*", ";"), 3) ;convert $sExclude to fit StringRegExp (not perfect but useable) $sTExclude = StringRegExpReplace($sTExclude, '([\Q\.+[^]$(){}=!\E])', '\\$1') ;thanks KaFu and Ascend4nt $sTExclude = StringReplace($sTExclude, "?", ".") $sTExclude = StringReplace($sTExclude, "*", ".*?") $sTExclude = StringReplace($sTExclude, ";", "|") For $iPCount = 1 To $aPath[0] Local $sPathItem = StringStripWS($aPath[$iPCount], 3) ;Strip leading and trailing spaces Local $sDelim = "|" ;reset $sDelim If StringRight($sPathItem, 1) <> "\" Then $sPathItem = $sPathItem & "\" ;check for trailing "\" ;return full-path or filename only ($iFlag 0,1,2 = Filename, $iFlag 4,5,6 = full path) If $iFlag > 3 Then $sDelim &= $sPathItem $TFlag = $iFlag - 4 Else $TFlag = $iFlag EndIf ;perform the search For $iFCount = 1 To $aFilter[0] Local $FilterItem = StringStripWS($aFilter[$iFCount], 3) ;Strip leading and trailing spaces If StringRegExp($FilterItem, "[\\/:<>|]") Then ContinueLoop ;Look for bad chars $hSearch = FileFindFirstFile($sPathItem & $FilterItem) If @error Then ContinueLoop Switch $TFlag Case 0 ;Files and Folders While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;check for exclude filename/folder If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop $sFileList &= $sDelim & $sFile WEnd Case 1 ;Files Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;If StringInStr(FileGetAttrib($sPath & $sFile), "D") <> 0 Then ContinueLoop; bypass folder (ver 3.3.0.0) If @extended Then ContinueLoop ;bypass folder (for Autoit versions > 3.3.0.0) ;check for exclude filename/folder If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop $sFileList &= $sDelim & $sFile WEnd Case 2 ;Folders Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;If StringInStr(FileGetAttrib($sPath & $sFile), "D") = 0 Then ContinueLoop; bypass file (ver 3.3.0.0) If @extended = 0 Then ContinueLoop ;bypass file (for Autoit versions > 3.3.0.0) ;check for exclude filename/folder If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop $sFileList &= $sDelim & $sFile WEnd Case Else Return SetError(3, 3, "") EndSwitch FileClose($hSearch) Next ;--------------- ;optional do a recursive search If $bRecursiv Then $hSearch = FileFindFirstFile($sPathItem & "*.*") If Not @error Then While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;If StringInStr(FileGetAttrib($sPath & $sFile), "D") = 0 Then ContinueLoop; bypass file (ver 3.3.0.0) If @extended = 0 Then ContinueLoop ;bypass file (for Autoit versions > 3.3.0.0) ;check for exclude folder If StringRegExp(StringRegExpReplace($sFile, "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\A" & $sTExclude & "\z") Then ContinueLoop ;call recursive search $sFileList &= _FileListToArrayEx3($sPathItem & $sFile, $sFilter, $iFlag, $bRecursiv, $sExclude, 0) WEnd FileClose($hSearch) EndIf EndIf Next ;$iPCount Else ;If Not $sExclude For $iPCount = 1 To $aPath[0] Local $sPathItem = StringStripWS($aPath[$iPCount], 3) ;Strip leading and trailing spaces Local $sDelim = "|" ;reset $sDelim If StringRight($sPathItem, 1) <> "\" Then $sPathItem = $sPathItem & "\" ;check for trailing "\" ;return full-path or filename only ($iFlag 0,1,2 = Filename, $iFlag 4,5,6 = full path) If $iFlag > 3 Then $sDelim &= $sPathItem $TFlag = $iFlag - 4 Else $TFlag = $iFlag EndIf ;perform the search For $iFCount = 1 To $aFilter[0] Local $FilterItem = StringStripWS($aFilter[$iFCount], 3) ;Strip leading and trailing spaces If StringRegExp($FilterItem, "[\\/:<>|]") Then ContinueLoop ;Look for bad chars $hSearch = FileFindFirstFile($sPathItem & $FilterItem) If @error Then ContinueLoop Switch $TFlag Case 0 ;Files and Folders While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop $sFileList &= $sDelim & $sFile WEnd Case 1 ;Files Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;If StringInStr(FileGetAttrib($sPath & $sFile), "D") <> 0 Then ContinueLoop; bypass folder (ver 3.3.0.0) If @extended Then ContinueLoop ;bypass folder (for Autoit versions > 3.3.0.0) $sFileList &= $sDelim & $sFile WEnd Case 2 ;Folders Only While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;If StringInStr(FileGetAttrib($sPath & $sFile), "D") = 0 Then ContinueLoop; bypass file (ver 3.3.0.0) If @extended = 0 Then ContinueLoop ;bypass file (for Autoit versions > 3.3.0.0) $sFileList &= $sDelim & $sFile WEnd Case Else Return SetError(3, 3, "") EndSwitch FileClose($hSearch) Next ;--------------- ;optional do a recursive search If $bRecursiv Then $hSearch = FileFindFirstFile($sPathItem & "*.*") If Not @error Then While True $sFile = FileFindNextFile($hSearch) If @error Then ExitLoop ;If StringInStr(FileGetAttrib($sPath & $sFile), "D") = 0 Then ContinueLoop; bypass file (ver 3.3.0.0) If @extended = 0 Then ContinueLoop ;bypass file (for Autoit versions > 3.3.0.0) ;call recursive search $sFileList &= _FileListToArrayEx3($sPathItem & $sFile, $sFilter, $iFlag, $bRecursiv, $sExclude, 0) WEnd FileClose($hSearch) EndIf EndIf Next ;$iPCount EndIf ;If $sExclude ;--------------- ;Set according return value Switch $iRetFormat Case 0 Return $sFileList Case 1 If $sFileList = "" Then Local $aRet[1] = [0] Return $aRet Else Return StringSplit(StringTrimLeft($sFileList, 1), "|", $iRetFormat) EndIf Case 2 If $sFileList = "" Then Local $aRet[0] Return $aRet Else Return StringSplit(StringTrimLeft($sFileList, 1), "|", $iRetFormat) EndIf Case Else Return SetError(4, 4, "") EndSwitch EndFunc ;==>_FileListToArrayEx3oÝ÷ Ø©®ÞuW«²*'¡ñbââ²ÔèºÚË©÷ùõ«¢+ØìU9 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