Skeletor Posted June 13, 2022 Share Posted June 13, 2022 Hi All, I might mess up on trying to explain, but here goes. I read this post about the directory tree level and sorting it by 'hierarchy' or 'level' subfolders. I tried the exampled and it works great, but how do you return only the Level 6 directory path?Example: C:\ = Level 1 C:\Temp = Level 2 C:\Temp\Foo = Level 3 C:\Temp\Foo\Bar = Level 4 C:\Temp\Foo\Bar\Lorem = Level 5C:\Temp\Foo\Bar\Loren\Epsum = Level 6 Local $aFolderPath, $x = 0 Local $aFolderPaths = _FileListToArrayRec(@ScriptDir, "*", 2, 1, 1, 2) _ArrayColInsert($aFolderPaths, 1) For $i = 1 To $aFolderPaths[0][0] $aFolderPath = StringSplit($aFolderPaths[$i][0], "\") If _ArraySearch($aFolderPaths, Number($aFolderPath[0] & "." & $x), 1, 0, 0, 0, 1, 1) > -1 Then $x += 1 $aFolderPaths[$i][1] = Number($aFolderPath[0] & "." & $x) Else $x = 0 While _ArraySearch($aFolderPaths, Number($aFolderPath[0] & "." & $x), 1, 0, 0, 0, 1, 1) > -1 $x += 1 WEnd $aFolderPaths[$i][1] = Number($aFolderPath[0] & "." & $x) EndIf Next _ArraySort($aFolderPaths, 1, 1, 0, 1) _ArrayDisplay($aFolderPaths) Directory Tree Level Kind RegardsSkeletor "Coffee: my defense against going postal." Microsoft Office Splash Screen | Basic Notepad Program (Beginner) | Transparent Splash Screen | Full Screen UI Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted June 13, 2022 Moderators Share Posted June 13, 2022 Skeletor, If you replace @ScriptDir with the full path of that level, the function will return folders from that level. There is an option to search down for a defined number of levels, but if you want to look for all Level 6 folders on the path, regardless of on which branch they reside, then you will have to get all the folders down to that level and then extract only those with the corresponding number of backslashes. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
Skeletor Posted June 14, 2022 Author Share Posted June 14, 2022 @Melba23 - thanks for the advise. After reading over your comment about 7 or 8 time, I got working on this, I finally found the answer. However, is this the right way to do this? Would like to know if my method is logical? expandcollapse popup#include <Array.au3> #include <File.au3> #include <MsgBoxConstants.au3> Local $aFolderPath, $x = 0 $aFolderPaths = _FileListToArrayRec(@UserProfileDir, "*", $FLTAR_FOLDERS, $FLTAR_RECUR, $FLTAR_SORT, $FLTAR_FULLPATH) _ArrayColInsert($aFolderPaths, 1) For $i = 1 To $aFolderPaths[0][0] $aFolderPath = StringSplit($aFolderPaths[$i][0], "\") If _ArraySearch($aFolderPaths, Number($aFolderPath[0] & "." & $x), 1, 0, 0, 0, 1, 1) > -1 Then $x += 1 $aFolderPaths[$i][1] = Number($aFolderPath[0]) ; Removed this => (& "." & $x) from Number($aFolderPath[0] & "." & $x) Else $x = 0 While _ArraySearch($aFolderPaths, Number($aFolderPath[0]), 1, 0, 0, 0, 1, 1) > -1 ; Removed this => (& "." & $x) from Number($aFolderPath[0] & "." & $x) $x += 1 WEnd $aFolderPaths[$i][1] = Number($aFolderPath[0] & "." & $x) EndIf Next _ArraySort($aFolderPaths, 1, 1, 0, 1) _ArrayDisplay($aFolderPaths) Local $FindArray = _ArrayFindAll($aFolderPaths, "6", Default, Default, Default, Default, 2) ; Searching for only Level 6 folder. Local $aFolderPathsCol[UBound($FindArray)][UBound($aFolderPaths, 2)] For $i = 0 To UBound($FindArray) -1 For $iI = 0 To UBound($aFolderPaths, 2) -1 $aFolderPathsCol[$i][$iI] = $aFolderPaths [$FindArray[$i]] [$iI] Next Next _ArraySort($aFolderPathsCol,1) _ArrayColDelete($aFolderPathsCol,1) _ArrayDisplay($aFolderPathsCol) Array = Achilles Heel for me. Kind RegardsSkeletor "Coffee: my defense against going postal." Microsoft Office Splash Screen | Basic Notepad Program (Beginner) | Transparent Splash Screen | Full Screen UI Link to comment Share on other sites More sharing options...
Moderators Solution Melba23 Posted June 15, 2022 Moderators Solution Share Posted June 15, 2022 Skeletor, I would do it this way: #include <Array.au3> #include <File.au3> ; Get the list of all folders $aFolderPaths = _FileListToArrayRec("M:", "*", $FLTAR_FOLDERS, $FLTAR_RECUR, $FLTAR_SORT, $FLTAR_FULLPATH) ; This will be the list of indices of folders to delete $sDeleteString = "" For $i = 1 To $aFolderPaths[0] ; Count number of "\" StringReplace($aFolderPaths[$i], "\", "") ; It is returned in @extended If @extended <> 6 Then ; If not at level 6 then add index of item to list to delete $sDeleteString &= $i & ";" EndIf Next ; Trim the finla and unwanted ";" $sDeleteString = StringTrimRight($sDeleteString, 1) ; Delete all the unwanted folders in one go _ArrayDelete($aFolderPaths, $sDeleteString) ; Reset the count $aFolderPaths[0] = UBound($aFolderPaths) - 1 ; And here we are! _ArrayDisplay($aFolderPaths, "", Default, 8) M23 Skeletor and pixelsearch 1 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 Link to comment Share on other sites More sharing options...
Skeletor Posted June 15, 2022 Author Share Posted June 15, 2022 @Melba23 .. This is simply amazing. To be honest, I never knew about the macro @extended, I have learnt something new today. Thank you for adding comments into the code, it helps me a lot to know what each section does and why it does it. THANK YOU! Kind RegardsSkeletor "Coffee: my defense against going postal." Microsoft Office Splash Screen | Basic Notepad Program (Beginner) | Transparent Splash Screen | Full Screen UI Link to comment Share on other sites More sharing options...
pixelsearch Posted June 15, 2022 Share Posted June 15, 2022 (edited) @Melba23 I like your way of using StringReplace() just for counting the number of times a character is found in a string (@extended) without assigning the result to a new string. I guess most of us don't think at this solution as often as we should, probably thinking unconsciously to this syntax... Local $sString = StringReplace() ...and not to the syntax you used : StringReplace() ; string returned won't be used, but @extended will. The original string is untouched in both cases, which seems unconsciously "a bit" less obvious with the syntax you used. Not sure I expressed this clearly, but you got the idea Edited June 15, 2022 by pixelsearch typo Link to comment Share on other sites More sharing options...
pixelsearch Posted June 15, 2022 Share Posted June 15, 2022 If you look at this link ("Count characters in a string") you'll see that the question was already asked and several answers were made (including @Jos alternative StringReplace) I'm pretty sure @Jon could add a quick C++ function in 5 minutes, maybe called "StringCount" where no string would need to be prepared and returned in the code (faster result) but only the number of times a character (or group of characters) are found in a string. Then we won't need to use the StringReplace alternative at all, keeping StringReplace to its natural behavior : return a string with replaced characters. Just my 2 cts... Link to comment Share on other sites More sharing options...
Deye Posted June 17, 2022 Share Posted June 17, 2022 There is no need to scan the entire drive for getting this done You can withdraw the search once the desired depth level has been reached. using a strategy, it is easy to determine what results should be added to the array using the functions FindFirstFile() FileFindNextFile() if you need an example for this i'll put it up so you can try it out Link to comment Share on other sites More sharing options...
mikell Posted June 17, 2022 Share Posted June 17, 2022 My 2 cents - for the fun (obviously) #include <Array.au3> #include <File.au3> ; Get the list of all folders $aFolderPaths = _FileListToArrayRec(@desktopdir, "*", $FLTAR_FOLDERS, $FLTAR_RECUR, $FLTAR_SORT, $FLTAR_FULLPATH) $k = 1 Local $aResults[1000] For $i = 1 To $aFolderPaths[0] $tmp = StringRegExpReplace($aFolderPaths[$i], '^((?:[^\\]+\\){6}[^\\]+)$', "$1") If @extended Then $aResults[$k] = $tmp $k += 1 EndIf Next $aResults[0] = $k ReDim $aResults[$k] _ArrayDisplay($aResults) Link to comment Share on other sites More sharing options...
jchd Posted June 17, 2022 Share Posted June 17, 2022 Pathes of the form \\server... or C:\temp\.\.\.\.\... escape that pattern. This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe hereRegExp tutorial: enough to get startedPCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta. SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt) Link to comment Share on other sites More sharing options...
mikell Posted June 17, 2022 Share Posted June 17, 2022 ... so my code should not be used in such cases jchd 1 Link to comment Share on other sites More sharing options...
rudi Posted June 21, 2022 Share Posted June 21, 2022 Another 2 cents to speed up the process: _FileListToArrayRec() will go through all the deeper folder levels, which are of no interest here. So with this code all levels beyond "6" will be ignored, speeding up the whole process: expandcollapse popup#include <File.au3> #include <Array.au3> #include <Debug.au3> $StartDir="C:\" ; " just for preserving the online forum formatting $StrHarvester="" $Deepth=0 $CurrentDir="" AdlibRegister("Status",2000) harvest($StartDir) AdlibUnRegister("Status") ToolTip("Done, Processing results...",100,100) ; strip off the final "|" $StrHarvester=StringTrimRight($StrHarvester,1) $aLevel_6_Dirs=StringSplit($StrHarvester,"|") _DebugArrayDisplay($aLevel_6_Dirs) Func harvest($_Dir) $Deepth+=1 $CurrentDir=$_Dir Local $aNextLevel $aNextLevel=_FileListToArray($_Dir,"*",2,1) if IsArray($aNextLevel) Then Switch $Deepth case 1 to 5 ; loop through next level Local $x for $x = 1 to $aNextLevel[0] if $aNextLevel[$x] = "." or $aNextLevel[$x] = ".." then ContinueLoop Else harvest($aNextLevel[$x]) EndIf Next case 6 ; add all found subdirs to the result string $StrHarvester &= _ArrayToString($aNextLevel,"|",1) & "|" case else ; ups, here we should never arrive! MsgBox(0, 'Gone too deep', "Level = " & $Deepth & @CRLF & _ $_Dir) EndSwitch Else ; no subdirs at this level EndIf $Deepth-=1 Return EndFunc Func Status() ToolTip($CurrentDir,MouseGetPos(0),MouseGetPos(1),"Level = " & $Deepth) ConsoleWrite($Deepth & @TAB & $CurrentDir & @CRLF) EndFunc Earth is flat, pigs can fly, and Nuclear Power is SAFE! Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted June 21, 2022 Moderators Share Posted June 21, 2022 Hi, Quote _FileListToArrayRec() will go through all the deeper folder levels, which are of no interest here. Not so. You can limit how far it goes into the tree by using negative values in the $iRecur parameter. In this case: $aFolderPaths = _FileListToArrayRec("M:", "*", $FLTAR_FOLDERS, -6, $FLTAR_SORT, $FLTAR_FULLPATH) will not go any deeper than you require. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
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