#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #Tidy_Parameters=/sf #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #Region ;**** Options AutoIt **** Opt("MustDeclareVars", 1) Opt("GUICloseOnESC", 1) Opt("GUIOnEventMode", 1) Opt("WinSearchChildren", 1) Opt("WinTextMatchMode", 1) Opt("WinTitleMatchMode", -2) #EndRegion ;**** Options AutoIt **** #Region ;**** Include AutoIt **** #include #include #include #EndRegion ;**** Include AutoIt **** #Region ;**** StringAddThousandsSep **** ; #FUNCTION# ==================================================================================================================== ; Name...........: _StringAddThousandsSepEx ; Description ...: Returns the original numbered string with the Thousands delimiter inserted. ; Syntax.........: _StringAddThousandsSep($sString[, $sThousands = -1[, $sDecimal = -1]]) ; Parameters ....: $sString - The string to be converted. ; $sThousands - Optional: The Thousands delimiter ; $sDecimal - Optional: The decimal delimiter ; Return values .: Success - The string with Thousands delimiter added. ; Author ........: SmOke_N (orignal _StringAddComma ; Modified.......: Valik (complete re-write, new function name), KaFu (copied from 3.3.0.0, as function is deprecated in newer AU versions) ; Remarks .......: ; Related .......: ; Link ..........; ; =============================================================================================================================== Func _StringAddThousandsSep($sString, $sThousands = -1, $sDecimal = -1) Local $sResult = "" ; Force string Local $rKey = "HKCU\Control Panel\International" If $sDecimal = -1 Then $sDecimal = RegRead($rKey, "sDecimal") If $sThousands = -1 Then $sThousands = RegRead($rKey, "sThousand") Local $aNumber = StringRegExp($sString, "(\D?\d+)\D?(\d*)", 1) ; This one works for negatives. If UBound($aNumber) = 2 Then Local $sLeft = $aNumber[0] While StringLen($sLeft) $sResult = $sThousands & StringRight($sLeft, 3) & $sResult $sLeft = StringTrimRight($sLeft, 3) WEnd ; Strip leading thousands separator $sResult = StringTrimLeft($sResult, StringLen($sThousands)) ; Strip leading thousands separator If $aNumber[1] <> "" Then $sResult &= $sDecimal & $aNumber[1] EndIf Return $sResult EndFunc ;==>_StringAddThousandsSep #EndRegion ;**** StringAddThousandsSep **** #Region ;**** RecFileListToArray **** ; #INDEX# ======================================================================================================================= ; Title .........: _RecFileListToArray ; AutoIt Version : v3.3.1.1 or higher ; Language ......: English ; Description ...: Lists files and\or folders in specified path with optional recursion to defined level and result sorting ; Note ..........: ; Author(s) .....: Melba23 ; Remarks .......: - Modified Array.au3 functions - credit: Jos van der Zande, LazyCoder, Tylo, Ultima, SolidSnake and gcriaco ; - SRE patterns - credit: various forum members and Spiff59 in particular ; - Despite the name, this UDF is iterative, not recursive ; =============================================================================================================================== ; #CURRENT# ===================================================================================================================== ; _RecFileListToArray: Lists files and\or folders in a specified path with optional recursion to defined level and result sorting ; =============================================================================================================================== ; #INTERNAL_USE_ONLY#============================================================================================================ ; _RFLTA_ListToMask ......; Convert include/exclude lists to SRE format ; _RFLTA_AddToList .......; Add element to list which is resized if necessary ; _RFLTA_AddFileLists ....; Add internal lists after resizing and optional sorting ; _RFLTA_FileListSearch ..; Search file match list for files associated with a folder ; _RFLTA_ArraySort .......; Wrapper for QuickSort function ; _RFLTA_QuickSort .......: Recursive array sort ; _RFLTA_ArrayConcatenate : Join 2 arrays ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _RecFileListToArray ; Description ...: Lists files and\or folders in a specified path with optional recursion to defined level and result sorting ; Syntax.........: _RecFileListToArray($sPath[, $sInclude_List = "*"[, $iReturn = 0[, $iRecur = 0[, $iSort = 0[, $iReturnPath = 1[, $sExclude_List = ""]]]]]]) ; Parameters ....: $sPath - Initial path used to generate filelist. If path ends in \ then folders will be returned with an ending \ ; $sInclude_List - Optional: filter for included results (default "*"). Multiple filters must be separated by ";" ; $iReturn - Optional: specifies whether to return files, folders or both ; |$iReturn = 0 (Default) Return both files and folders ; |$iReturn = 1 Return files only ; |$iReturn = 2 Return folders only ; $iRecur - Optional: specifies whether to search recursively in subfolders and to what level ; |$iRecur = 1 Search in all subfolders (unlimited recursion) ; |$iRecur = 0 (Default) Do not search in subfolders ; |$iRecur = Negative integer - Search in subfolders to specified depth ; $iSort - Optional: sort ordered in alphabetical and depth order ; |$iSort = 0 - Not sorted (Default) ; |$iSort = 1 - Sorted ; |$iSort = 2 - Sorted with faster algorithm (assumes files sorted within each folder - requires NTFS drive) ; $iReturnPath - Optional: specifies displayed path of results ; |$iReturnPath = 0 File/folder name only ; |$iReturnPath = 1 (Default) Relative to initial path ; |$iReturnPath = 2 Full path included ; $sExclude_List - Optional: filter for excluded results (default ""). Multiple filters must be separated by ";" ; Requirement(s).: v3.3.1.1 or higher ; Return values .: Success: One-dimensional array made up as follows: ; |$array[0] = Number of Files\Folders returned ; |$array[1] = 1st File\Folder ; |$array[2] = 2nd File\Folder ; |... ; |$array[n] = nth File\Folder ; Failure: Null string and @error = 1 with @extended set as follows: ; |1 = Path not found or invalid ; |2 = Invalid $sInclude_List ; |3 = Invalid $iReturn ; |4 = Invalid $iRecur ; |5 = Invalid $iSort ; |6 = Invalid $iReturnPath ; |7 = Invalid $sExclude_List ; |8 = No files/folders found ; Author ........: Melba23 ; Modified.......: GaRy delaMer ; Remarks .......: Compatible with existing _FileListToArray syntax ; Related .......: ; Link ..........; ; Example .......; Yes ; =============================================================================================================================== Func _RecFileListToArray($sInitialPath, $sInclude_List = "*", $iReturn = 0, $iRecur = 0, $iSort = 0, $iReturnPath = 1, $sExclude_List = "") Local $asReturnList[100] = [0], $asFileMatchList[100] = [0], $asRootFileMatchList[100] = [0], $asFolderMatchList[100] = [0], $asFolderSearchList[100] = [1] Local $sFolderSlash = "", $iMaxLevel, $sInclude_List_Mask, $sExclude_List_Mask, $hSearch, $fFolder, $sRetPath = "", $sCurrentPath, $sName Local $asFolderFileSectionList[100][2] = [[0, 0]], $sFolderToFind, $iFileSectionStartIndex, $iFileSectionEndIndex ; Check for valid path If Not FileExists($sInitialPath) Then Return SetError(1, 1, "") ; Check if folders should have trailing \ and ensure that initial path does have one If StringRight($sInitialPath, 1) = "\" Then $sFolderSlash = "\" Else $sInitialPath = $sInitialPath & "\" EndIf ; Add path to folder search list $asFolderSearchList[1] = $sInitialPath ; Check for valid recur value If $iRecur > 1 Or Not IsInt($iRecur) Then Return SetError(1, 4, "") ; If required, determine \ count for max recursive level setting If $iRecur < 0 Then StringReplace($sInitialPath, "\", "", 2) $iMaxLevel = @extended - $iRecur EndIf ; Create Include List mask If $sInclude_List = "" Or $sInclude_List = "*" Or $sInclude_List = Default Then $sInclude_List_Mask = ".+" ; Set mask to exclude base folder with NULL name Else If Not _RFLTA_ListToMask($sInclude_List_Mask, $sInclude_List) Then Return SetError(1, 2, "") EndIf ; Create Exclude List mask If $sExclude_List = "" Then $sExclude_List_Mask = ":" ; Set unmatchable mask Else If Not _RFLTA_ListToMask($sExclude_List_Mask, $sExclude_List) Then Return SetError(1, 7, "") EndIf ; Verify other parameters If Not ($iReturn = 0 Or $iReturn = 1 Or $iReturn = 2) Then Return SetError(1, 3, "") If Not ($iSort = 0 Or $iSort = 1 Or $iSort = 2) Then Return SetError(1, 5, "") If Not ($iReturnPath = 0 Or $iReturnPath = 1 Or $iReturnPath = 2) Then Return SetError(1, 6, "") ; 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 $sRetPath = StringReplace($sCurrentPath, $sInitialPath, "") Case 2 ; Full path $sRetPath = $sCurrentPath EndSwitch ; Get search handle $hSearch = FileFindFirstFile($sCurrentPath & "*") ; If folder empty move to next in list If $hSearch = -1 Then ContinueLoop EndIf ; If sorting files and folders with paths then store folder name and position of associated files in list If Not ($iReturn) And $iSort And $iReturnPath Then _RFLTA_AddToList($asFolderFileSectionList, $sRetPath, $asFileMatchList[0] + 1) EndIf ; Search folder While 1 $sName = FileFindNextFile($hSearch) ; Check for end of folder If @error Then ExitLoop EndIf ; Set subfolder flag - @extended set in 3.3.1.1 + $fFolder = @extended ; If folder then check whether to add to search list If $fFolder Then Switch $iRecur Case 1 ; Always add _RFLTA_AddToList($asFolderSearchList, $sCurrentPath & $sName & "\") Case 0 ; Never add ; Do nothing Case Else ; Add if max level not exceeded StringReplace($sCurrentPath, "\", "", 0, 2) If @extended < $iMaxLevel Then _RFLTA_AddToList($asFolderSearchList, $sCurrentPath & $sName & "\") EndIf EndSwitch EndIf ; Match name against Include/Exclude masks If StringRegExp($sName, $sInclude_List_Mask) And Not StringRegExp($sName, $sExclude_List_Mask) Then If $iSort Then ; Save in relevant folders for later sorting If $fFolder Then _RFLTA_AddToList($asFolderMatchList, $sRetPath & $sName & $sFolderSlash) Else ; Select required list for files If $sCurrentPath = $sInitialPath Then _RFLTA_AddToList($asRootFileMatchList, $sRetPath & $sName) Else _RFLTA_AddToList($asFileMatchList, $sRetPath & $sName) EndIf EndIf Else ; Save directly in return list ; Check file/folder type against required return value If $fFolder + $iReturn <> 2 Then ; Add final "\" to folders if required If $fFolder Then $sName &= $sFolderSlash _RFLTA_AddToList($asReturnList, $sRetPath & $sName) EndIf EndIf EndIf WEnd ; Close current search FileClose($hSearch) WEnd If $iSort Then ; Check if any file/folders have been added If $asRootFileMatchList[0] = 0 And $asFileMatchList[0] = 0 And $asFolderMatchList[0] = 0 Then Return SetError(1, 8, "") Switch $iReturn Case 2 ; Folders only ; Correctly size folder match list ReDim $asFolderMatchList[$asFolderMatchList[0] + 1] ; Copy size folder match array $asReturnList = $asFolderMatchList ; Simple sort list _RFLTA_ArraySort($asReturnList) Case 1 ; Files only If $iReturnPath = 0 Then ; names only so simple sort suffices ; Combine file match lists _RFLTA_AddFileLists($asReturnList, $asRootFileMatchList, $asFileMatchList) ; Simple sort combined file list _RFLTA_ArraySort($asReturnList) Else ; Combine sorted file match lists _RFLTA_AddFileLists($asReturnList, $asRootFileMatchList, $asFileMatchList, 1) EndIf Case 0 ; Both files and folders If $iReturnPath = 0 Then ; names only so simple sort suffices ; Combine file match lists _RFLTA_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] _RFLTA_ArrayConcatenate($asReturnList, $asFolderMatchList) ; Simple sort final list _RFLTA_ArraySort($asReturnList) 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 _RFLTA_ArraySort($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 _RFLTA_ArraySort($asFolderMatchList, 1, $asFolderMatchList[0]) ; Work through folder list For $i = 1 To $asFolderMatchList[0] ; Format folder name for search If $sFolderSlash Then $sFolderToFind = $asFolderMatchList[$i] Else $sFolderToFind = $asFolderMatchList[$i] & "\" EndIf ; Find folder in FolderFileSectionList For $j = 1 To $asFolderFileSectionList[0][0] If $sFolderToFind = $asFolderFileSectionList[$j][0] Then ExitLoop Next ; 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 _RFLTA_ArraySort($asFileMatchList, $iFileSectionStartIndex, $iFileSectionEndIndex) EndIf ; Add folder to return list $asReturnList[$iNextInsertionIndex] = $asFolderMatchList[$i] $iNextInsertionIndex += 1 ; Add files to return list For $j = $iFileSectionStartIndex To $iFileSectionEndIndex $asReturnList[$iNextInsertionIndex] = $asFileMatchList[$j] $iNextInsertionIndex += 1 Next Next EndIf EndSwitch Else ; No sort ; Check if any file/folders have been added If $asReturnList[0] = 0 Then Return SetError(1, 8, "") ; Remove any unused return list elements from last ReDim ReDim $asReturnList[$asReturnList[0] + 1] EndIf Return $asReturnList EndFunc ;==>_RecFileListToArray ; #INTERNAL_USE_ONLY#============================================================================================================ ; Name...........: _RFLTA_AddFileLists ; Description ...: Add internal lists after resizing and optional sorting ; Syntax ........: _RFLTA_AddFileLists(ByRef $asTarget, $asSource_1, $asSource_2[, $iSort = 0]) ; Parameters ....: $asReturnList - Base list ; $asRootFileMatchList - First list to add ; $asFileMatchList - Second list to add ; $iSort - (Optional) Whether to sort lists before adding ; |$iSort = 0 (Default) No sort ; |$iSort = 1 Sort in descending alphabetical order ; Return values .: None - array modified ByRef ; Author ........: Melba23 ; Remarks .......: This function is used internally by _RecFileListToArray ; =============================================================================================================================== Func _RFLTA_AddFileLists(ByRef $asTarget, $asSource_1, $asSource_2, $iSort = 0) ; Correctly size root file match array ReDim $asSource_1[$asSource_1[0] + 1] ; Simple sort root file match array if required If $iSort = 1 Then _RFLTA_ArraySort($asSource_1) ; Copy root file match array $asTarget = $asSource_1 ; Add file match count $asTarget[0] += $asSource_2[0] ; Correctly size file match array ReDim $asSource_2[$asSource_2[0] + 1] ; Simple sort file match array if required If $iSort = 1 Then _RFLTA_ArraySort($asSource_2) ; Add file match array _RFLTA_ArrayConcatenate($asTarget, $asSource_2) EndFunc ;==>_RFLTA_AddFileLists ; #INTERNAL_USE_ONLY#============================================================================================================ ; Name...........: _RFLTA_AddToList ; Description ...: Add element to [?] or [?][2] list which is resized if necessary ; Syntax ........: _RFLTA_AddToList(ByRef $asList, $vValue_0, [$vValue_1]) ; Parameters ....: $aList - List to be added to ; $vValue_0 - Value to add (to [0] element in [?][2] array if $vValue_1 exists) ; $vValue_1 - Value to add to [1] element in [?][2] array (optional) ; Return values .: None - array modified ByRef ; Author ........: Melba23 ; Remarks .......: This function is used internally by _RecFileListToArray ; =============================================================================================================================== Func _RFLTA_AddToList(ByRef $aList, $vValue_0, $vValue_1 = -1) If $vValue_1 = -1 Then ; [?] array ; 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]] = $vValue_0 Else ; [?][2] array $aList[0][0] += 1 If UBound($aList) <= $aList[0][0] Then ReDim $aList[UBound($aList) * 2][2] $aList[$aList[0][0]][0] = $vValue_0 $aList[$aList[0][0]][1] = $vValue_1 EndIf EndFunc ;==>_RFLTA_AddToList ; #INTERNAL_USE_ONLY#============================================================================================================ ; Name...........: _RFLTA_ArrayConcatenate ; Description ...: Joins 2 arrays ; Syntax ........: _RFLTA_ArrayConcatenate(ByRef $avArrayTarget, Const ByRef $avArraySource) ; Parameters ....: $avArrayTarget - Base array ; $avArraySource - Array to add from element 1 onwards ; Return values .: None - array modified ByRef ; Author ........: Ultima ; Modified.......: Melba23 ; Remarks .......: This function is used internally by _RecFileListToArray ; =============================================================================================================================== Func _RFLTA_ArrayConcatenate(ByRef $avArrayTarget, Const ByRef $avArraySource) Local $iUBoundTarget = UBound($avArrayTarget) - 1, $iUBoundSource = UBound($avArraySource) ReDim $avArrayTarget[$iUBoundTarget + $iUBoundSource] For $i = 1 To $iUBoundSource - 1 $avArrayTarget[$iUBoundTarget + $i] = $avArraySource[$i] Next EndFunc ;==>_RFLTA_ArrayConcatenate ; #INTERNAL_USE_ONLY#============================================================================================================ ; Name...........: _RFLTA_ArraySort ; Description ...: Wrapper for QuickSort function ; Syntax ........: _RFLTA_ArraySort(ByRef $avArray) ; Parameters ....: $avArray - Array to sort ; $iStart - Index to start sort ; $iEnd - Index to end sort ; Return values .: None - array modified ByRef ; Author ........: Jos van der Zande, LazyCoder, Tylo, Ultima ; Modified.......: Melba23 ; Remarks .......: This function is used internally by _RecFileListToArray ; =============================================================================================================================== Func _RFLTA_ArraySort(ByRef $avArray, $iStart = 1, $iEnd = -99) If $iEnd = -99 Then $iEnd = UBound($avArray) - 1 _RFLTA_QuickSort($avArray, $iStart, $iEnd) EndFunc ;==>_RFLTA_ArraySort ; #INTERNAL_USE_ONLY#============================================================================================================ ; Name...........: _RFLTA_FileListSearch ; Description ...: Search file array for beginning and end indices of folder associated files ; Syntax ........: _RFLTA_FileListSearch(Const ByRef $avArray, $vValue) ; Parameters ....: $avArray - Array to search ($asFileMatchList) ; $vValue - Value to search for (Folder name from $asFolderMatchList) ; $iIndex - Index to begin search (search down from here - and then from here to top if not found) ; $sSlash - \ if folder names end in \ - else empty string ; Return values .: Success: Array holding top and bottom indices of folder associated files ; Failure: Returns -1 ; Author ........: Melba23 ; Modified.......: ; Remarks .......: This function is used internally by _RecFileListToArray ; =============================================================================================================================== Func _RFLTA_FileListSearch(Const ByRef $avArray, $vValue, $iIndex, $sSlash) Local $aRet[2] ; Add final \ if required If Not $sSlash Then $vValue &= "\" ; Start by getting top match - search down from start index For $i = $iIndex To $avArray[0] ; SRE gives path less filename If StringRegExpReplace($avArray[$i], "(^.*\\)(.*)", "\1") = $vValue Then ExitLoop Next If $i > $avArray[0] Then ; No match found so look from start index upwards If $iIndex = $avArray[0] Then $iIndex -= 1 For $i = $iIndex + 1 To 1 Step -1 If StringRegExpReplace($avArray[$i], "(^.*\\)(.*)", "\1") = $vValue Then ExitLoop Next ; If still no match - return " nothing found" for empty folder If $i = 0 Then Return SetError(1, 0, "") ; Set index of bottom file $aRet[1] = $i ; Now look for top match For $i = $aRet[1] To 1 Step -1 If StringRegExpReplace($avArray[$i], "(^.*\\)(.*)", "\1") <> $vValue Then ExitLoop Next ; Set top match $aRet[0] = $i + 1 Else ; Set index of top associated file $aRet[0] = $i ; Now look for bottom match - find first file which does not match For $i = $aRet[0] To $avArray[0] If StringRegExpReplace($avArray[$i], "(^.*\\)(.*)", "\1") <> $vValue Then ExitLoop Next ; Set bottom match $aRet[1] = $i - 1 EndIf Return $aRet EndFunc ;==>_RFLTA_FileListSearch ; #INTERNAL_USE_ONLY#============================================================================================================ ; Name...........: _RFLTA_ListToMask ; Description ...: Convert include/exclude lists to SRE format ; Syntax ........: _RFLTA_ListToMask(ByRef $sMask, $sList) ; Parameters ....: $asMask - Include/Exclude mask to create ; $asList - Include/Exclude list to convert ; Return values .: Success: 1 ; Failure: 0 ; Author ........: SRE patterns developed from those posted by various forum members and Spiff59 in particular ; Remarks .......: This function is used internally by _RecFileListToArray ; =============================================================================================================================== Func _RFLTA_ListToMask(ByRef $sMask, $sList) ; Check for invalid characters within list If StringRegExp($sList, "\\|/|:|\<|\>|\|") Then Return 0 ; Strip WS and insert | for ; $sList = StringReplace(StringStripWS(StringRegExpReplace($sList, "\s*;\s*", ";"), 3), ";", "|") ; Convert to SRE pattern $sList = StringReplace(StringReplace(StringRegExpReplace($sList, "(\^|\$|\.)", "\\$1"), "?", "."), "*", ".*?") ; Add prefix and suffix $sMask = "(?i)^(" & $sList & ")\z" Return 1 EndFunc ;==>_RFLTA_ListToMask ; #INTERNAL_USE_ONLY#============================================================================================================ ; Name...........: _RFLTA_QuickSort ; Description ...: Recursive array sort ; Syntax ........: _RFLTA_QuickSort(ByRef $avArray, ByRef $iStart, ByRef $iEnd) ; Parameters ....: $avArray - Array to sort in descending alphabetical order ; $iStart - Start index ; $iEnd - End index ; Return values .: None - array modified ByRef ; Author ........: Jos van der Zande, LazyCoder, Tylo, Ultima ; Modified.......: Melba23 ; Remarks .......: This function is used internally by _RFLTA_ArraySort ; =============================================================================================================================== Func _RFLTA_QuickSort(ByRef $avArray, ByRef $iStart, ByRef $iEnd) Local $vTmp If ($iEnd - $iStart) < 15 Then Local $i, $j, $vCur For $i = $iStart + 1 To $iEnd $vTmp = $avArray[$i] If IsNumber($vTmp) Then For $j = $i - 1 To $iStart Step -1 $vCur = $avArray[$j] If ($vTmp >= $vCur And IsNumber($vCur)) Or (Not IsNumber($vCur) And StringCompare($vTmp, $vCur) >= 0) Then ExitLoop $avArray[$j + 1] = $vCur Next Else For $j = $i - 1 To $iStart Step -1 If (StringCompare($vTmp, $avArray[$j]) >= 0) Then ExitLoop $avArray[$j + 1] = $avArray[$j] Next EndIf $avArray[$j + 1] = $vTmp Next Return EndIf Local $L = $iStart, $R = $iEnd, $vPivot = $avArray[Int(($iStart + $iEnd) / 2)], $fNum = IsNumber($vPivot) Do If $fNum Then While ($avArray[$L] < $vPivot And IsNumber($avArray[$L])) Or (Not IsNumber($avArray[$L]) And StringCompare($avArray[$L], $vPivot) < 0) $L += 1 WEnd While ($avArray[$R] > $vPivot And IsNumber($avArray[$R])) Or (Not IsNumber($avArray[$R]) And StringCompare($avArray[$R], $vPivot) > 0) $R -= 1 WEnd Else While (StringCompare($avArray[$L], $vPivot) < 0) $L += 1 WEnd While (StringCompare($avArray[$R], $vPivot) > 0) $R -= 1 WEnd EndIf If $L <= $R Then $vTmp = $avArray[$L] $avArray[$L] = $avArray[$R] $avArray[$R] = $vTmp $L += 1 $R -= 1 EndIf Until $L > $R _RFLTA_QuickSort($avArray, $iStart, $R) _RFLTA_QuickSort($avArray, $L, $iEnd) EndFunc ;==>_RFLTA_QuickSort #EndRegion ;**** RecFileListToArray **** #Region ;**** Variables & Constantes Globales **** Global Const $PROGRESS_CONTINUE = 0 Global Const $PROGRESS_CANCEL = 1 Global Const $PROGRESS_STOP = 2 Global Const $PROGRESS_QUIET = 3 Global Const $MOVE_FILE_REPLACE_EXISTSING = 0x00000001 Global Const $MOVE_FILE_COPY_ALLOWED = 0x00000002 Global Const $MOVE_FILE_DELAY_UNTIL_REBOOT = 0x00000004 Global Const $MOVE_FILE_WRITE_THROUGH = 0x00000008 Global Const $MOVE_FILE_CREATE_HARDLINK = 0x00000010 Global Const $MOVE_FILE_FAIL_IF_NOT_TRACKABLE = 0x00000020 Global Enum $iTitle = 0, $iLeft, $iTop, $iLblSourceDestCopy, $iLblSourceDestMove, $iLblFile, $iLblTotal, $iButtonPause, $iButtonCancel Global $_aGUI_MFAWP[9] = ["MultiFile_Action_WithProgress", _ ; 0 Titre -1, _ ; 1 Left 20, _ ; 2 Top 'Copie le fichier:\n"%s"\nvers:\n"%s"', _ ; 3 Label Progression Source/Destination 'Déplace le fichier:\n"%s"\nvers:\n"%s"', _ ; 4 Label Progression Source/Destination "Fichier:", _ ; 5 Label Fichier "Total:", _ ; 6 Label Total "Pause", _ ; 7 Texte Boutons Pause "Annuler"] ; 8 Texte Boutons Annuler Global Enum $ihGui = 0, $iDllKernel, $iDllUser, $iTimer, $iCountFiles, $iFilesSize, $iCount, $iSizeTransfered, _ $iCtrl_SourceDestination, $iCtrl_FilePercent, $iCtrl_FileProgress, $iCtrl_FilesPercent, $iCtrl_FilesProgress, _ $iCtrl_ButtonPause, $iCtrl_ButtonCancel #EndRegion ;**** Variables & Constantes Globales **** If @ScriptName = "Files-2.au3" Then _Exemple_MFAWP() Func _Exemple_MFAWP() ; Copie _GUI_MFAWP_SetText("Sauvegarde le fichier:\n%s\nvers:\n%s") Local $Ret = _MultiFile_Action_WithProgress(@ScriptDir, @ScriptDir & "\Save", "*", False) If @error Then ConsoleWrite("Erreur: " & @error & " " & @extended & @LF) Else _ArrayDisplay($Ret) EndIf ; Déplacement _GUI_MFAWP_SetPos(-1, -1) _GUI_MFAWP_SetText(Default, "Déplace le fichier:\n%s\nvers:\n%s") Local $Ret = _MultiFile_Action_WithProgress(@ScriptDir & "\Save", @ScriptDir & "\Save\Save", "*", True, 0, False) If @error Then ConsoleWrite("Erreur: " & @error & " " & @extended & @LF) Else _ArrayDisplay($Ret) EndIf EndFunc ;==>_Exemple_MFAWP ; #INTERNAL_USE_ONLY#============================================================================================================ ; Name...........: ; Description ...: ; Syntax ........: ; Parameters ....: ; Return values .: ; Author ........: ; Remarks .......: This function is used internally by _MultiFile_Action_WithProgress ; =============================================================================================================================== Func _GUI_MFAWP_Create(ByRef $aMFAWP) If Not IsDeclared("PBS_SMOOTH") Then Local Const $PBS_SMOOTH = 1 If Not IsDeclared("WS_POPUPWINDOW") Then Local Const $WS_POPUPWINDOW = 0x80880000 If Not IsDeclared("WS_EX_TOPMOST") Then Local Const $WS_EX_TOPMOST = 0x00000008 If Not IsDeclared("WS_EX_TOOLWINDOW") Then Local Const $WS_EX_TOOLWINDOW = 0x00000080 If Not IsDeclared("WS_EX_COMPOSITED") Then Local Const $WS_EX_COMPOSITED = 0x02000000 $aMFAWP[0] = GUICreate($_aGUI_MFAWP[0], 520, 220, $_aGUI_MFAWP[1], $_aGUI_MFAWP[2], $WS_POPUPWINDOW, BitOR($WS_EX_TOPMOST, $WS_EX_TOOLWINDOW, $WS_EX_COMPOSITED)) ; Label Source => Destination $aMFAWP[8] = GUICtrlCreateLabel($_aGUI_MFAWP[3], 10, 10, 500, 65) GUICtrlSetFont(-1, 10, 400, 0, "Courier New") ; Label Source GUICtrlCreateLabel($_aGUI_MFAWP[5], 10, 83, 70, 16) GUICtrlSetFont(-1, 11, 600, 0, "Courier New") ; Label Progression fichier en cours % $aMFAWP[9] = GUICtrlCreateLabel("0 %", 85, 83, 500, 16) GUICtrlSetFont(-1, 11, 600, 0, "Courier New") ; Progression fichier en cours $aMFAWP[10] = GUICtrlCreateProgress(10, 100, 500, 20, $PBS_SMOOTH) GUICtrlCreateLabel($_aGUI_MFAWP[6], 10, 133, 70, 16) GUICtrlSetFont(-1, 11, 600, 0, "Courier New") ; Label Progression totale $aMFAWP[11] = GUICtrlCreateLabel("0 %", 85, 133, 440, 16) GUICtrlSetFont(-1, 11, 600, 0, "Courier New") ; Progression totale $aMFAWP[12] = GUICtrlCreateProgress(10, 150, 500, 20, $PBS_SMOOTH) ; Boutons Pause $aMFAWP[13] = GUICtrlCreateButton($_aGUI_MFAWP[7], 120, 185, 80, 25) GUICtrlSetFont(-1, 9, 400, 0, "Arial") ; Boutons Annuler $aMFAWP[14] = GUICtrlCreateButton($_aGUI_MFAWP[8], 320, 185, 80, 25) GUICtrlSetFont(-1, 9, 400, 0, "Arial") GUISetState() EndFunc ;==>_GUI_MFAWP_Create ; #INTERNAL_USE_ONLY#============================================================================================================ ; Name...........: ; Description ...: ; Syntax ........: ; Parameters ....: ; Return values .: ; Author ........: ; Remarks .......: This function is used internally by _MultiFile_Action_WithProgress ; =============================================================================================================================== Func _GUI_MFAWP_ProgressSet($FileSize, $BytesTransferred, $StreamSize, $StreamBytesTransferred, $dwStreamNumber, $dwCallbackReason, $hSourceFile, $hDestinationFile, $lpData) #comments-start DWORD CALLBACK CopyProgressRoutine( __in LARGE_INTEGER TotalFileSize, __in LARGE_INTEGER TotalBytesTransferred, __in LARGE_INTEGER StreamSize, __in LARGE_INTEGER StreamBytesTransferred, __in DWORD dwStreamNumber, __in DWORD dwCallbackReason, __in HANDLE hSourceFile, __in HANDLE hDestinationFile, __in_opt LPVOID lpData ); #comments-end Local $aMFAWP = StringSplit($lpData, ":", 2) If _IsPressed("1B", Int($aMFAWP[2])) Then Return $PROGRESS_CANCEL Local $CursorInfo = GUIGetCursorInfo($aMFAWP[0]) If _IsPressed("01", Int($aMFAWP[2])) And ($CursorInfo[4] = Int($aMFAWP[13])) Then Return $PROGRESS_STOP If _IsPressed("01", Int($aMFAWP[2])) And ($CursorInfo[4] = Int($aMFAWP[14])) Then Return $PROGRESS_CANCEL Local $sPercent = Round($BytesTransferred / $FileSize * 100, 0) GUICtrlSetData($aMFAWP[9], $sPercent & " %") GUICtrlSetData($aMFAWP[10], $sPercent) Local $sPercentAll = Round(($aMFAWP[7] + $BytesTransferred) / $aMFAWP[5] * 100, 0) Local $iTime = TimerDiff($aMFAWP[3]) Local $iTotalTime = Ceiling($iTime / 1000 / ($sPercentAll + 0.1) * 100) Local $iTransferRate = _StringAddThousandsSep(Int($aMFAWP[7] / $iTotalTime / 1000), ".", ",") GUICtrlSetData($aMFAWP[11], $sPercentAll & " % Temps: " & Int($iTime / 1000) & "/" & $iTotalTime & " s " & $aMFAWP[6] & "/" & $aMFAWP[4] & " (" & $iTransferRate & " KB/s)") GUICtrlSetData($aMFAWP[12], $sPercentAll) Return $PROGRESS_CONTINUE EndFunc ;==>_GUI_MFAWP_ProgressSet Func _GUI_MFAWP_SetPos($Left = Default, $Top = Default) If $Left = Default Then $Left = -1 $_aGUI_MFAWP[1] = $Left If $Top = Default Then $Top = 30 $_aGUI_MFAWP[2] = $Top EndFunc ;==>_GUI_MFAWP_SetPos Func _GUI_MFAWP_SetText($Text1 = 'Copie le fichier:\n"%s"\nvers:\n"%s"', $Text2 = 'Déplace le fichier:\n"%s"\nvers:\n"%s"', $TextButton1 = "Pause", $TextButton2 = "Annuler") If $Text1 = Default Or $Text1 = -1 Then $Text1 = 'Copie le fichier:\n"%s"\nvers:\n"%s"' $_aGUI_MFAWP[3] = $Text1 If $Text2 = Default Or $Text2 = -1 Then $Text2 = 'Déplace le fichier:\n"%s"\nvers:\n"%s"' $_aGUI_MFAWP[4] = $Text2 If $TextButton1 = Default Or $TextButton1 = -1 Then $TextButton1 = "Pause" $_aGUI_MFAWP[7] = $TextButton1 If $TextButton2 = Default Or $TextButton2 = -1 Then $TextButton2 = "Annuler" $_aGUI_MFAWP[8] = $TextButton2 EndFunc ;==>_GUI_MFAWP_SetText ; #FUNCTION# ==================================================================================================================== ; Name...........: _MultiFile_Action_WithProgress ; Description ...: Copy or Move multiles Files ; Syntax.........: _MultiFile_Action_WithProgress($aSources[, $sDestPath = ""[, $sFilter = "*.*"[, $bMove = False[, $iRecurse = 0[, $bOverWrite = False[, $sPreFix = "!Copie"[, $sExclude = ""]]]]]]]) ; Parameters ....: ; Requirement(s).: v3.3.1.1 or higher ; Return values .: Success: 2-dimensional array ; Failure: 0 and @error set as follows: ; |1 _RecFileListToArray Error = $aSources Path not found or invalid ; |2 _RecFileListToArray Error = Invalid $sFilter ; |3 _RecFileListToArray Error = Invalid $iReturn ; |4 _RecFileListToArray Error = Invalid $iRecur ; |5 _RecFileListToArray Error = Invalid $iSort ; |6 _RecFileListToArray Error = Invalid $iReturnPath ; |7 _RecFileListToArray Error = Invalid $sExclude_List ; |8 _RecFileListToArray Error = No files/folders found ; |9 = Invalid $aSources not an array ; |10 = Invalid $aSource array[0] not a number ; |11 = Invalid $sDestPath Can't create Directory ; |12 = Can't create $sDestPath SubDirectory ; Author ........: Tom99, progandy, eukalyptus and Oscar (www.autoit.de) ; Modified.......: GaRy delaMer ; Remarks .......: ; =============================================================================================================================== Func _MultiFile_Action_WithProgress($aSources, $sDestPath = "", $sFilter = "*.*", $bMove = False, $iRecurse = 0, $bOverWrite = True, $sPreFix = "!Copie", $sExclude = "") Local $Action = "copier" If $bMove == True Or $bMove > 0 Then $Action = "déplacer" ToolTip("Veuillez patienter..." & @LF & "Construction de la liste des fichiers à " & $Action & ".", @DesktopWidth / 2 - 100, 30) Local $sSourcePath = "" If IsString($aSources) Then $sSourcePath = _PathFull($aSources) If StringRight($sSourcePath, 1) <> "\" Then $sSourcePath &= "\" $aSources = _RecFileListToArray($sSourcePath, $sFilter, 0, $iRecurse, 1, 2, $sExclude) If @error Then Return SetError(@error, @extended, ToolTip("")) EndIf If Not IsArray($aSources) Then Return SetError(9, 0, ToolTip("")) If Not IsNumber($aSources[0]) Then Return SetError(10, 0, ToolTip("")) ;~ $sDestPath = _PathFull($sDestPath) If StringRight($sDestPath, 1) <> "\" Then $sDestPath &= "\" If Not FileExists($sDestPath) Then If Not DirCreate($sDestPath) Then Return SetError(11, 0, 0) EndIf Local $aMFAWP[15] = [0, _ ; 0 GUI Handle DllOpen("kernel32.dll"), _ ; 1 DllOpen kernel32.dll DllOpen("user32.dll"), _ ; 2 DllOpen user32.dll TimerInit(), _ ; 3 TimerInit $aSources[0], _ ; 4 Nombre de fichier à copier 0, _ ; 5 Taille globale en octets 0, _ ; 6 Compteur 0, _ ; 7 Taille transferer 0, _ ; 8 GUICtrl Label Source => Destination 0, _ ; 9 GUICtrl Label % fichier en cours 0, _ ; 10 GUICtrl Progress fichier en cours 0, _ ; 11 GUICtrl Label % Total 0, _ ; 12 GUICtrl Progress Total 0, _ ; 13 GUICtrl Bouton Pause 0] ; 14 GUICtrl Bouton Annuler Local $aReturn[$aSources[0] + 1][2] = [[$aSources[0], $Action]] Local $sNewFolder, $sFile, $sNewFile, $Number For $i = 1 To $aSources[0] ; Création des dossiers et sous-dossiers $sNewFolder = StringTrimLeft(StringLeft($aSources[$i], StringInStr($aSources[$i], "\", 0, -1)), StringLen($sSourcePath)) If Not FileExists($sDestPath & $sNewFolder) Then If Not DirCreate($sDestPath & $sNewFolder) Then Return SetError(12, 0, 0) EndIf ; Nom du Fichier $sFile = StringMid($aSources[$i], StringInStr($aSources[$i], "\", 0, -1) + 1) If $sFile = "" Then ReDim $aReturn[UBound($aReturn) - 1][2] $aReturn[0][0] -= 1 ContinueLoop EndIf ; Nouveau nom du fichier si il exite et qu'on écrase pas avec Le préfixe et un compteur $Number = 0 $sNewFile = $sFile While $bOverWrite = False And FileExists($sDestPath & $sNewFolder & $sNewFile) If $Number = 0 Then $sNewFile = $sPreFix & " " & $sFile Else $sNewFile = $sPreFix & " " & $Number & " " & $sFile EndIf $Number += 1 WEnd ; Valeur de retour $aReturn[$i][0] = _PathFull($aSources[$i]) $aReturn[$i][1] = _PathFull($sDestPath & $sNewFolder & $sNewFile) $aMFAWP[5] += FileGetSize($aSources[$i]) Next ToolTip("") Local $sShowSource, $sShowDestin, $aDllReturn, $sDatas Local $CallBack = DllCallbackRegister("_GUI_MFAWP_ProgressSet", "int", "uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;str") ; Création de la GUI Local $oldGUICloseOnESC = Opt("GUICloseOnESC", 0) _GUI_MFAWP_Create($aMFAWP) For $i = 1 To $aReturn[0][0] ; Voir pour une découpe du Path x:\1st Dir\[...]\Last Dir\FileName $sShowSource = StringRegExpReplace($aReturn[$i][0], "(.{15})(.*)(.{40})", "$1" & "[...]" & "$3") $sShowDestin = StringRegExpReplace($aReturn[$i][1], "(.{15})(.*)(.{40})", "$1" & "[...]" & "$3") ; Compteur des fichiers $aMFAWP[6] += 1 ; Passage des données à la fonction CallBack $sDatas = _ArrayToString($aMFAWP, ":") ; Appel des API windows et leurs Paramètres Switch $Action Case "copier" GUICtrlSetData($aMFAWP[8], StringFormat($_aGUI_MFAWP[3], $sShowSource, $sShowDestin)) #comments-start BOOL WINAPI CopyFileEx( __in LPCTSTR lpExistingFileName, __in LPCTSTR lpNewFileName, __in_opt LPPROGRESS_ROUTINE lpProgressRoutine, __in_opt LPVOID lpData, __in_opt LPBOOL pbCancel, __in DWORD dwCopyFlags ); #comments-end $aDllReturn = DllCall($aMFAWP[1], "int", "CopyFileExA", _ "str", $aReturn[$i][0], _ "str", $aReturn[$i][1], _ "ptr", DllCallbackGetPtr($CallBack), _ "str", $sDatas, _ "int", 0, _ "int", 0) Case "déplacer" GUICtrlSetData($aMFAWP[8], StringFormat($_aGUI_MFAWP[4], $sShowSource, $sShowDestin)) ; Courcircuite le CallBack car bug windows ??? la fonction est pas appelée GUICtrlSetData($aMFAWP[$iCtrl_FilePercent], "100 %") GUICtrlSetData($aMFAWP[$iCtrl_FileProgress], 100) GUICtrlSetData($aMFAWP[$iCtrl_FilesPercent], Round($i * 100 / $aMFAWP[$iCountFiles], 0) & " %") GUICtrlSetData($aMFAWP[$iCtrl_FilesProgress], $i * 100 / $aMFAWP[$iCountFiles]) #comments-start BOOL WINAPI MoveFileWithProgress( __in LPCTSTR lpExistingFileName, __in_opt LPCTSTR lpNewFileName, __in_opt LPPROGRESS_ROUTINE lpProgressRoutine, __in_opt LPVOID lpData, __in DWORD dwFlags ); #comments-end $aDllReturn = DllCall($aMFAWP[1], "int", "MoveFileWithProgressA", _ "str", $aReturn[$i][0], _ "str", $aReturn[$i][1], _ "ptr", DllCallbackGetPtr($CallBack), _ "str", $sDatas, _ "int", $MOVE_FILE_COPY_ALLOWED + $MOVE_FILE_WRITE_THROUGH + $MOVE_FILE_REPLACE_EXISTSING) EndSwitch ; Augmente la Taille globale transférer $aMFAWP[7] += FileGetSize($aReturn[$i][0]) ; Si l'opération est annulé: click sur le bouton ou touche Esc sort de la boucle If $aDllReturn[0] = 0 Then ReDim $aReturn[$i][2] $aReturn[0][0] = $i - 1 ExitLoop EndIf Next ; Libèrer les objets DllCallbackFree($CallBack) GUIDelete($aMFAWP[0]) DllClose($aMFAWP[1]) DllClose($aMFAWP[2]) Opt("GUICloseOnESC", $oldGUICloseOnESC) Return $aReturn EndFunc ;==>_MultiFile_Action_WithProgress