corgano Posted March 16, 2019 Posted March 16, 2019 (edited) I have a list of files from _FileListToArrayRec. I then _ArraySort them and put them into a treeview so i can browse the structure of the folders. It works but it sorts the files too literally, giving me this: A file B file B subfolder A subfile B subfile C subfile C subfolder A subsubfile B subsubfile D subfile E subfile C file C subfolder A subfile A subfolder A subsubfile B subfile What I want is in each subfolder, It to list the FOLDERS in alphabetical folder, and then the FILES. B subfolder C subfolder A subsubfile B subsubfile A subfile B subfile C subfile D subfile E subfile C subfolder A subfolder A subsubfile A subfile B subfile A file B file C file Most threads I found when googling this say something along the lines of "Just get a list of folders and files separately, and then put the two arrays files after folders" but that only works for a single folder, it doesn't work for recursive folders. Has anyone found a way to get the desired result? Edited March 16, 2019 by corgano 0x616e2069646561206973206c696b652061206d616e20776974686f7574206120626f64792c20746f206669676874206f6e6520697320746f206e657665722077696e2e2e2e2e
Bilgus Posted March 16, 2019 Posted March 16, 2019 Does specifying the full path being returned help? $iReturnPath = $FLTAR_RELPATH $FLTAR_NOPATH (0) - File/folder name only $FLTAR_RELPATH (1) - Relative to initial path (Default) $FLTAR_FULLPATH (2) - Full path included
Bilgus Posted March 16, 2019 Posted March 16, 2019 Also the function includes a sort option? $iSort[optional] Sort results in alphabetical and depth order $FLTAR_NOSORT (0) - Not sorted (Default) $FLTAR_SORT (1) - Sorted $FLTAR_FASTSORT (2) - Sorted with faster algorithm (assumes files in folder returned sorted - requires NTFS and not guaranteed)
corgano Posted March 16, 2019 Author Posted March 16, 2019 $FLTAR_FASTSORT gives me almost EXACTLY what I want - but it sorts it FILESA-Z then FOLDERSA-Z. Any way to make it have FOLDERS first? 0x616e2069646561206973206c696b652061206d616e20776974686f7574206120626f64792c20746f206669676874206f6e6520697320746f206e657665722077696e2e2e2e2e
FrancescoDiMuro Posted March 16, 2019 Posted March 16, 2019 @corgano If you just want to reverse the elements in the array, why don't you use _ArrayReverse() ? Click here to see my signature: Spoiler ALWAYS GOOD TO READ: Forum Rules Forum Etiquette
Moderators Melba23 Posted March 16, 2019 Moderators Posted March 16, 2019 (edited) corgano, It was a design decision to place the files in the root folder first - and not that difficult to change them to the end. Does this modified function do what you want? expandcollapse popup#include <File.au3> #include <Array.au3> ; New constants for File.au3 Global $FLTAR_FILESFIRST = 1, $FLTAR_FILESLAST = 0 $aArray = _FileListToArrayRec_Mod("M:\Program\Au3 Scripts\Forum Help Scripts\", "*", $FLTAR_FILESFOLDERS, $FLTAR_RECUR, $FLTAR_FASTSORT, $FLTAR_RELPATH, $FLTAR_FILESFIRST) _ArrayDisplay($aArray, "", Default, 8) $aArray = _FileListToArrayRec_Mod("M:\Program\Au3 Scripts\Forum Help Scripts\", "*", $FLTAR_FILESFOLDERS, $FLTAR_RECUR, $FLTAR_FASTSORT, $FLTAR_RELPATH, $FLTAR_FILESLAST) _ArrayDisplay($aArray, "", Default, 8) Func _FileListToArrayRec_Mod($sFilePath, $sMask = "*", $iReturn = $FLTAR_FILESFOLDERS, $iRecur = $FLTAR_NORECUR, $iSort = $FLTAR_NOSORT, $iReturnPath = $FLTAR_RELPATH, $iFilesFirst = $FLTAR_FILESFIRST) If Not FileExists($sFilePath) Then Return SetError(1, 1, "") ; Check for Default keyword If $sMask = Default Then $sMask = "*" If $iReturn = Default Then $iReturn = $FLTAR_FILESFOLDERS If $iRecur = Default Then $iRecur = $FLTAR_NORECUR If $iSort = Default Then $iSort = $FLTAR_NOSORT If $iReturnPath = Default Then $iReturnPath = $FLTAR_RELPATH If $iFilesFirst = Default Then $iFilesFirst = $FLTAR_FILESFIRST ; Check for valid recur value If $iRecur > 1 Or Not IsInt($iRecur) Then Return SetError(1, 6, "") Local $bLongPath = False ; Check for valid path If StringLeft($sFilePath, 4) == "\\?\" Then $bLongPath = True EndIf Local $sFolderSlash = "" ; Check if folders should have trailing \ and ensure that initial path does have one If StringRight($sFilePath, 1) = "\" Then $sFolderSlash = "\" Else $sFilePath = $sFilePath & "\" EndIf Local $asFolderSearchList[100] = [1] ; Add path to folder search list $asFolderSearchList[1] = $sFilePath Local $iHide_HS = 0, _ $sHide_HS = "" ; Check for H or S omitted If BitAND($iReturn, $FLTAR_NOHIDDEN) Then $iHide_HS += 2 $sHide_HS &= "H" $iReturn -= $FLTAR_NOHIDDEN EndIf If BitAND($iReturn, $FLTAR_NOSYSTEM) Then $iHide_HS += 4 $sHide_HS &= "S" $iReturn -= $FLTAR_NOSYSTEM EndIf Local $iHide_Link = 0 ; Check for link/junction omitted If BitAND($iReturn, $FLTAR_NOLINK) Then $iHide_Link = 0x400 $iReturn -= $FLTAR_NOLINK EndIf Local $iMaxLevel = 0 ; If required, determine \ count for max recursive level setting If $iRecur < 0 Then StringReplace($sFilePath, "\", "", 0, $STR_NOCASESENSEBASIC) $iMaxLevel = @extended - $iRecur EndIf Local $sExclude_List = "", $sExclude_List_Folder = "", $sInclude_List = "*" ; Check mask parameter Local $aMaskSplit = StringSplit($sMask, "|") ; Check for multiple sections and set values Switch $aMaskSplit[0] Case 3 $sExclude_List_Folder = $aMaskSplit[3] ContinueCase Case 2 $sExclude_List = $aMaskSplit[2] ContinueCase Case 1 $sInclude_List = $aMaskSplit[1] EndSwitch Local $sInclude_File_Mask = ".+" ; Create Include mask for files If $sInclude_List <> "*" Then If Not __FLTAR_ListToMask($sInclude_File_Mask, $sInclude_List) Then Return SetError(1, 2, "") EndIf Local $sInclude_Folder_Mask = ".+" ; Set Include mask for folders Switch $iReturn Case 0 ; Folders affected by mask if not recursive Switch $iRecur Case 0 ; Folders match mask for compatibility $sInclude_Folder_Mask = $sInclude_File_Mask EndSwitch Case 2 ; Folders affected by mask $sInclude_Folder_Mask = $sInclude_File_Mask EndSwitch Local $sExclude_File_Mask = ":" ; Create Exclude List mask for files If $sExclude_List <> "" Then If Not __FLTAR_ListToMask($sExclude_File_Mask, $sExclude_List) Then Return SetError(1, 3, "") EndIf Local $sExclude_Folder_Mask = ":" ; Create Exclude mask for folders If $iRecur Then If $sExclude_List_Folder Then If Not __FLTAR_ListToMask($sExclude_Folder_Mask, $sExclude_List_Folder) Then Return SetError(1, 4, "") EndIf ; If folders only If $iReturn = 2 Then ; Folders affected by normal mask $sExclude_Folder_Mask = $sExclude_File_Mask EndIf Else ; Folders affected by normal mask $sExclude_Folder_Mask = $sExclude_File_Mask EndIf ; Verify other parameters If Not ($iReturn = 0 Or $iReturn = 1 Or $iReturn = 2) Then Return SetError(1, 5, "") If Not ($iSort = 0 Or $iSort = 1 Or $iSort = 2) Then Return SetError(1, 7, "") If Not ($iReturnPath = 0 Or $iReturnPath = 1 Or $iReturnPath = 2) Then Return SetError(1, 8, "") If Not ($iFilesFirst = 0 Or $iFilesFirst = 1) Then Return SetError(1, 9, "") ; Prepare for DllCall if required If $iHide_Link Then Local $tFile_Data = DllStructCreate("struct;align 4;dword FileAttributes;uint64 CreationTime;uint64 LastAccessTime;uint64 LastWriteTime;" & _ "dword FileSizeHigh;dword FileSizeLow;dword Reserved0;dword Reserved1;wchar FileName[260];wchar AlternateFileName[14];endstruct") Local $hDLL = DllOpen('kernel32.dll'), $aDLL_Ret EndIf Local $asReturnList[100] = [0] Local $asFileMatchList = $asReturnList, $asRootFileMatchList = $asReturnList, $asFolderMatchList = $asReturnList Local $bFolder = False, _ $hSearch = 0, _ $sCurrentPath = "", $sName = "", $sRetPath = "" Local $iAttribs = 0, _ $sAttribs = '' Local $asFolderFileSectionList[100][2] = [[0, 0]] ; 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, $sFilePath, "") Case 2 ; Full path If $bLongPath Then $sRetPath = StringTrimLeft($sCurrentPath, 4) Else $sRetPath = $sCurrentPath EndIf EndSwitch ; Get search handle - use code matched to required listing If $iHide_Link Then ; Use DLL code $aDLL_Ret = DllCall($hDLL, 'handle', 'FindFirstFileW', 'wstr', $sCurrentPath & "*", 'struct*', $tFile_Data) If @error Or Not $aDLL_Ret[0] Then ContinueLoop EndIf $hSearch = $aDLL_Ret[0] Else ; Use native code $hSearch = FileFindFirstFile($sCurrentPath & "*") ; If folder empty move to next in list If $hSearch = -1 Then ContinueLoop EndIf EndIf ; If sorting files and folders with paths then store folder name and position of associated files in list If $iReturn = 0 And $iSort And $iReturnPath Then __FLTAR_AddToList($asFolderFileSectionList, $sRetPath, $asFileMatchList[0] + 1) EndIf $sAttribs = '' ; Search folder - use code matched to required listing While 1 ; Use DLL code If $iHide_Link Then ; Use DLL code $aDLL_Ret = DllCall($hDLL, 'int', 'FindNextFileW', 'handle', $hSearch, 'struct*', $tFile_Data) ; Check for end of folder If @error Or Not $aDLL_Ret[0] Then ExitLoop EndIf ; Extract data $sName = DllStructGetData($tFile_Data, "FileName") ; Check for .. return - only returned by the DllCall If $sName = ".." Then ContinueLoop EndIf $iAttribs = DllStructGetData($tFile_Data, "FileAttributes") ; Check for hidden/system attributes and skip if found If $iHide_HS And BitAND($iAttribs, $iHide_HS) Then ContinueLoop EndIf ; Check for link attribute and skip if found If BitAND($iAttribs, $iHide_Link) Then ContinueLoop EndIf ; Set subfolder flag $bFolder = False If BitAND($iAttribs, 16) Then $bFolder = True EndIf Else ; Reset folder flag $bFolder = False ; Use native code $sName = FileFindNextFile($hSearch, 1) ; Check for end of folder If @error Then ExitLoop EndIf $sAttribs = @extended ; Check for folder If StringInStr($sAttribs, "D") Then $bFolder = True EndIf ; Check for Hidden/System If StringRegExp($sAttribs, "[" & $sHide_HS & "]") Then ContinueLoop EndIf EndIf ; If folder then check whether to add to search list If $bFolder Then Select Case $iRecur < 0 ; Check recur depth StringReplace($sCurrentPath, "\", "", 0, $STR_NOCASESENSEBASIC) If @extended < $iMaxLevel Then ContinueCase ; Check if matched to masks EndIf Case $iRecur = 1 ; Full recur If Not StringRegExp($sName, $sExclude_Folder_Mask) Then ; Add folder unless excluded __FLTAR_AddToList($asFolderSearchList, $sCurrentPath & $sName & "\") EndIf ; Case $iRecur = 0 ; Never add ; Do nothing EndSelect EndIf If $iSort Then ; Save in relevant folders for later sorting If $bFolder Then If StringRegExp($sName, $sInclude_Folder_Mask) And Not StringRegExp($sName, $sExclude_Folder_Mask) Then __FLTAR_AddToList($asFolderMatchList, $sRetPath & $sName & $sFolderSlash) EndIf Else If StringRegExp($sName, $sInclude_File_Mask) And Not StringRegExp($sName, $sExclude_File_Mask) Then ; Select required list for files If $sCurrentPath = $sFilePath Then __FLTAR_AddToList($asRootFileMatchList, $sRetPath & $sName) Else __FLTAR_AddToList($asFileMatchList, $sRetPath & $sName) EndIf EndIf EndIf Else ; Save directly in return list If $bFolder Then If $iReturn <> 1 And StringRegExp($sName, $sInclude_Folder_Mask) And Not StringRegExp($sName, $sExclude_Folder_Mask) Then __FLTAR_AddToList($asReturnList, $sRetPath & $sName & $sFolderSlash) EndIf Else If $iReturn <> 2 And StringRegExp($sName, $sInclude_File_Mask) And Not StringRegExp($sName, $sExclude_File_Mask) Then __FLTAR_AddToList($asReturnList, $sRetPath & $sName) EndIf EndIf EndIf WEnd ; Close current search If $iHide_Link Then DllCall($hDLL, 'int', 'FindClose', 'ptr', $hSearch) Else FileClose($hSearch) EndIf WEnd ; Close the DLL if needed If $iHide_Link Then DllClose($hDLL) EndIf ; Sort results if required If $iSort Then Switch $iReturn Case 2 ; Folders only ; Check if any folders found If $asFolderMatchList[0] = 0 Then Return SetError(1, 9, "") ; Correctly size folder match list ReDim $asFolderMatchList[$asFolderMatchList[0] + 1] ; Copy size folder match array $asReturnList = $asFolderMatchList ; Simple sort list __ArrayDualPivotSort($asReturnList, 1, $asReturnList[0]) Case 1 ; Files only ; Check if any files found If $asRootFileMatchList[0] = 0 And $asFileMatchList[0] = 0 Then Return SetError(1, 9, "") If $iReturnPath = 0 Then ; names only so simple sort suffices ; Combine file match lists __FLTAR_AddFileLists($asReturnList, $asRootFileMatchList, $asFileMatchList) ; Simple sort combined file list __ArrayDualPivotSort($asReturnList, 1, $asReturnList[0]) Else ; Combine sorted file match lists __FLTAR_AddFileLists($asReturnList, $asRootFileMatchList, $asFileMatchList, 1) EndIf Case 0 ; Both files and folders ; Check if any root files or folders found If $asRootFileMatchList[0] = 0 And $asFolderMatchList[0] = 0 Then Return SetError(1, 9, "") If $iReturnPath = 0 Then ; names only so simple sort suffices ; Combine file match lists __FLTAR_AddFileLists($asReturnList, $asRootFileMatchList, $asFileMatchList) ; Set correct count for folder add $asReturnList[0] += $asFolderMatchList[0] ; Resize and add file match array ReDim $asFolderMatchList[$asFolderMatchList[0] + 1] _ArrayConcatenate($asReturnList, $asFolderMatchList, 1) ; Simple sort final list __ArrayDualPivotSort($asReturnList, 1, $asReturnList[0]) Else ; Size return list Local $asReturnList[$asFileMatchList[0] + $asRootFileMatchList[0] + $asFolderMatchList[0] + 1] $asReturnList[0] = $asFileMatchList[0] + $asRootFileMatchList[0] + $asFolderMatchList[0] ; Sort root file list __ArrayDualPivotSort($asRootFileMatchList, 1, $asRootFileMatchList[0]) ; Set insertion index Local $iNextInsertionIndex = 1 If $iFilesFirst = 1 Then ; Add the sorted root files at the beginning For $i = 1 To $asRootFileMatchList[0] $asReturnList[$iNextInsertionIndex] = $asRootFileMatchList[$i] $iNextInsertionIndex += 1 Next EndIf ; Sort folder list __ArrayDualPivotSort($asFolderMatchList, 1, $asFolderMatchList[0]) Local $sFolderToFind = "" ; Work through folder list For $i = 1 To $asFolderMatchList[0] ; Add folder to return list $asReturnList[$iNextInsertionIndex] = $asFolderMatchList[$i] $iNextInsertionIndex += 1 ; Format folder name for search If $sFolderSlash Then $sFolderToFind = $asFolderMatchList[$i] Else $sFolderToFind = $asFolderMatchList[$i] & "\" EndIf Local $iFileSectionEndIndex = 0, $iFileSectionStartIndex = 0 ; Find folder in FolderFileSectionList For $j = 1 To $asFolderFileSectionList[0][0] ; If found then deal with files If $sFolderToFind = $asFolderFileSectionList[$j][0] Then ; Set file list indexes $iFileSectionStartIndex = $asFolderFileSectionList[$j][1] If $j = $asFolderFileSectionList[0][0] Then $iFileSectionEndIndex = $asFileMatchList[0] Else $iFileSectionEndIndex = $asFolderFileSectionList[$j + 1][1] - 1 EndIf ; Sort files if required If $iSort = 1 Then __ArrayDualPivotSort($asFileMatchList, $iFileSectionStartIndex, $iFileSectionEndIndex) EndIf ; Add files to return list For $k = $iFileSectionStartIndex To $iFileSectionEndIndex $asReturnList[$iNextInsertionIndex] = $asFileMatchList[$k] $iNextInsertionIndex += 1 Next ExitLoop EndIf Next Next If $iFilesFirst = 0 Then ; Add the sorted root files at the end For $i = 1 To $asRootFileMatchList[0] $asReturnList[$iNextInsertionIndex] = $asRootFileMatchList[$i] $iNextInsertionIndex += 1 Next EndIf EndIf EndSwitch Else ; No sort ; Check if any file/folders have been added If $asReturnList[0] = 0 Then Return SetError(1, 9, "") ; Remove any unused return list elements from last ReDim ReDim $asReturnList[$asReturnList[0] + 1] EndIf Return $asReturnList EndFunc ;==>_FileListToArrayRec_Mod If so, we might consider a formal modification to the UDF to make the order user-selectable using a new parameter. M23 Edited March 16, 2019 by Melba23 Amended example script - again Skysnake 1 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area
Skysnake Posted March 16, 2019 Posted March 16, 2019 3 hours ago, Melba23 said: If so, we might consider a formal modification to the UDF to make the order user-selectable using a new parameter. Yes, please Skysnake Why is the snake in the sky?
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