blindwig Posted June 23, 2005 Share Posted June 23, 2005 My function _FileGetTreeList is used to get the directory structure listed in an array, like doing a "dir /ad/s/b" and saving it to an array. This function can display a progress meter so you can see how far into the tree it is (also so you don't think it has frozen)CODE;===============================================================================;; Function Name: _FileGetTreeList; Description: Returns a recursive list of directories; Parameter(s): $Path = root path to begin the listing from; $ProgressTitle = A title to put on a progress window. Empty String = no progress window; Requirement(s): $Path is an existing directory; Return Value(s): A 1-based array containing the full path of all found directories; Note: Upon return, @Extended will contain a count of files (non-folders) found while searching for folders; Author(s): Mike Ratzlaff <mike@ratzlaff.org>; Revision: 20050622A;;===============================================================================;Func _FileGetTreeList($Path, $ProgressTitle = @ScriptName) Dim $aDirList[100], $TotalFiles = 0 If $ProgressTitle <> '' Then ProgressOn($ProgressTitle, 'Scanning directories...', '', -1, -1, 16) If _FileIsDir($Path) Then $TotalFiles = __FileGetTreeList($aDirList, $Path, $ProgressTitle) EndIf If $ProgressTitle <> '' Then ProgressOff() SetExtended($TotalFiles) ReDim $aDirList[$aDirList[0]+1] Return $aDirListEndFuncFunc __FileGetTreeList(ByRef $aDirList, $Path, $ProgressTitle) Dim $hndSearch_Dirs, $FileCount If $ProgressTitle <> '' Then ProgressSet(random(99), $Path) ;Add the current directory on to the list $aDirList[0] = $aDirList[0] + 1 If $aDirList[0] > UBound($aDirList) - 1 Then ReDim $aDirList[$aDirList[0] + 20] $aDirList[$aDirList[0]] = $Path ;Scan for more directories $hndSearch_Dirs = FileFindFirstFile($Path & '\*') If $hndSearch_Dirs <> -1 Then $sFileName = FileFindNextFile($hndSearch_Dirs) While Not @error If _FileIsDir($Path & '\' & $sFileName) Then ;Recurse into the directory, if it's not a special directory If $sFileName <> '.' And $sFileName <> '..' Then $FileCount = $FileCount + __FileGetTreeList($aDirList, $Path & '\' & $sFileName, $ProgressTitle) EndIf Else ;Add to the filecount $FileCount = $FileCount + 1 EndIf $sFileName = FileFindNextFile($hndSearch_Dirs) WEnd EndIf FileClose($hndSearch_Dirs) Return $FileCountEndFuncMy _FileFindAllR function will return a list of files, found recursively, that match a given mask and attribute filter. This function also has an optional progress meter. The speed has been optimized by pre-fetching the directory structure and file count, so that these items don't have to be calculated dynamically.CODE;===============================================================================;; Function Name: _FileFindAllR; Description: Returns a recursive list of files; Parameter(s): $Path = root path to begin the listing from; $Mask = file mask to match; $AttribFilter = File Attributes to filter files through. See _FileFilterAttrib for details; $ProgressTitle = A title to put on a progress window. Empty String = no progress window; Requirement(s): $Path is an existing directory; Return Value(s): A 1-based array containing the full path of all found files; Author(s): Mike Ratzlaff <mike@ratzlaff.org>; Revision: 20050622A;;===============================================================================;;Returns a recursive list of files under $Path, matching $Mask, and filtered through $AttribFilterFunc _FileFindAllR($Path, $Mask='*', $AttribFilter='dhs', $ProgressTitle = @ScriptName) Dim $i, $aDirList = _FileGetTreeList($Path, $ProgressTitle), $FileList[@extended + 1] If $ProgressTitle <> '' Then ProgressOn($ProgressTitle, 'Scanning files...', '', -1, -1, 16) For $i = 1 to $aDirList[0] If $ProgressTitle <> '' Then ProgressSet($i * 100 / $aDirList[0], $aDirList[$i]) __FileFindAllR($FileList, $aDirList[$i], $Mask, $AttribFilter) Next If $ProgressTitle <> '' Then ProgressOff() ReDim $FileList[$FileList[0]+1] Return $FileListEndFuncFunc __FileFindAllR(ByRef $aFileList, $Path, $Mask, $AttribFilter) Dim $hndSearch_Files $hndSearch_Files = FileFindFirstFile($Path & '\' & $Mask) If $hndSearch_Files <> -1 Then $sFileName = FileFindNextFile($hndSearch_Files) While Not @error If _FileFilterAttrib($Path & '\' & $sFileName, $AttribFilter) And $sFileName <> '.' And $sFileName <> '..' Then $aFileList[0] = $aFileList[0] + 1 $aFileList[$aFileList[0]] = $Path & '\' & $sFileName EndIf $sFileName = FileFindNextFile($hndSearch_Files) WEnd FileClose($hndSearch_Files) EndIf EndFuncThese functions require my _FileFilterAttrib function, and also my _FileIsDir function:CODE;===============================================================================;; Function Name: _FileIsDir; Description: Returns true or false weather given file is a directory or not; Parameter(s): $Path; Requirement(s): ; Return Value(s): 0 = not a directory or does not exist, 1 = file exists and is a directory; Author(s): Mike Ratzlaff <mike@ratzlaff.org>; Revision: 20050623A;;===============================================================================;Func _FileIsDir($Path) ;This function checkes to see if $FileName exists and if it is a Directory If StringInStr(FileGetAttrib($Path),'D') Then Return 1 Return 0EndFunc Cheekybugger 1 My UDF Threads:Pseudo-Hash: Binary Trees, Flat TablesFiles: Filter by Attribute, Tree List, Recursive Find, Recursive Folders Size, exported to XMLArrays: Nested, Pull Common Elements, Display 2dSystem: Expand Environment Strings, List Drives, List USB DrivesMisc: Multi-Layer Progress Bars, Binary FlagsStrings: Find Char(s) in String, Find String in SetOther UDF Threads I Participated:Base64 Conversions Link to comment Share on other sites More sharing options...
blindwig Posted July 28, 2005 Author Share Posted July 28, 2005 I rewrote the _FileGetTreeList() function. It now has a proper (meaningful) progress bar, and the array grows gemetrically instead of arithmetically, so the routine is a lot faster for large trees. I use my _FileTruncPath() function, to display the paths as you go: CODE ;Truncates $sPath so that its length is <= $iSize Func _FileTruncPath($sPath, $iSize) ;split file from path Local $iSplit = StringInStr($sPath, '\', 0, -1) If $iSplit Then $sFile = StringMid($sPath, $iSplit) $sPath = StringLeft($sPath, $iSplit - 1) Else $sFile = $sPath $sPath = '' EndIf ;truncate and return new path Local $iPath = StringLen($sPath), $iFile = StringLen($sFile) If $iPath + $iFile <= $iSize Then Return $sPath & $sFile ElseIf $iFile > $iSize - 3 Then Return '...' & StringRight($sFile, $iSize - 3) Else Return StringLeft($sPath, $iSize - 3 - $iFile) & '...' & $sFile EndIf EndFunc And here's the new _FileGetTreeList() function: CODE ;=============================================================================== ; ; Function Name: _FileGetTreeList ; Description: Returns a recursive list of directories ; Parameter(s): $sPath = root path to begin the listing from ; $ProgressTitle = A title to put on a progress window. Empty String = no progress window ; Requirement(s): $sPath is an existing directory ; Return Value(s): A 1-based array containing the full path of all found directories ; Note: Upon return, @Extended will contain a count of all files and folders found while searching for folders ; Author(s): Mike Ratzlaff <mike@ratzlaff.org> ; Revision: 20050728A ; ;=============================================================================== ; Func _FileGetTreeList($sPath, $ProgressTitle = 'Mapping Directory Tree...') Local $aDirList[100], $TotalFiles = 0 If $ProgressTitle <> '' Then _ProgressCreate ($ProgressTitle, '', @ScriptName) If _FileIsDir($sPath) Then If $ProgressTitle = '' Then $TotalFiles = __FileGetTreeList($aDirList, $sPath, 0, 0) Else $TotalFiles = __FileGetTreeList($aDirList, $sPath, 0, 100) EndIf EndIf If $ProgressTitle <> '' Then _ProgressDelete () SetExtended($TotalFiles) ReDim $aDirList[$aDirList[0] + 1] Return $aDirList EndFunc ;==>_FileGetTreeList Func __FileGetTreeList(ByRef $aDirList, $sPath, $ProCur, $ProMax) If $ProMax > 0 Then _ProgressUpdate ($ProCur, _FileTruncPath($sPath, 60)) ;Add the current directory to the global list $aDirList[0] = $aDirList[0] + 1 If $aDirList[0] > UBound($aDirList) - 1 Then ReDim $aDirList[$aDirList[0] * 2] $aDirList[$aDirList[0]] = $sPath ;Scan for more directories Local $hndSearch_Dirs = FileFindFirstFile($sPath & '\*'), $FileCount, $aFolders[100] If $hndSearch_Dirs <> - 1 Then $sFileName = FileFindNextFile($hndSearch_Dirs) While Not @error ;Add this entry to the total count $FileCount = $FileCount + 1 ;If this entry is a normal folder, add it to the local list If _FileIsDir($sPath & '\' & $sFileName) And $sFileName <> '.' And $sFileName <> '..' Then $aFolders[0] = $aFolders[0] + 1 If $aFolders[0] >= UBound($aFolders) Then ReDim $aFolders[$aFolders[0] * 2] $aFolders[$aFolders[0]] = $sPath & '\' & $sFileName EndIf ;look for the next entry $sFileName = FileFindNextFile($hndSearch_Dirs) WEnd EndIf FileClose($hndSearch_Dirs) ;Recurse into local folders Local $i, $fSlice = $ProMax / $aFolders[0], $sProgress For $i = 1 To $aFolders[0] $FileCount = $FileCount + __FileGetTreeList($aDirList, $aFolders[$i], $ProCur + $fSlice * ($i - 1), $fSlice) Next Return $FileCount EndFunc ;==>__FileGetTreeList My UDF Threads:Pseudo-Hash: Binary Trees, Flat TablesFiles: Filter by Attribute, Tree List, Recursive Find, Recursive Folders Size, exported to XMLArrays: Nested, Pull Common Elements, Display 2dSystem: Expand Environment Strings, List Drives, List USB DrivesMisc: Multi-Layer Progress Bars, Binary FlagsStrings: Find Char(s) in String, Find String in SetOther UDF Threads I Participated:Base64 Conversions Link to comment Share on other sites More sharing options...
Freedom Posted December 16, 2005 Share Posted December 16, 2005 WoW, blindwig you are my hero! This was just what I was looking for. Thx for funcs and keep up the good work. For some reason the code tags are not working properly. When I copy and past your script it just ends up on one line. Anyway to avoid this? Link to comment Share on other sites More sharing options...
Freedom Posted December 16, 2005 Share Posted December 16, 2005 I got the copy and past to work by first pasting into wordpad and then copying and pasting that into Scite followed by Tidy! Damn that was annoying! Link to comment Share on other sites More sharing options...
brandonm Posted January 2, 2006 Share Posted January 2, 2006 Man, this rocks! Just what I've been looking for for my ftp client! Thanks! 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