blindwig Posted August 6, 2005 Share Posted August 6, 2005 There's plenty of times that I need to find the total size of a directory (and all subdirectories). And then it's nice to be able to go to each of those subdirectories and see what their total size is, etc.So I wrote a function that uses nested arrays to handle the job. Here's the code:expandcollapse popup;Returns a Nested array ;[0][0]=number of lines ;[0][1]=path ;[0][2]=total size in bytes ;[x][0]=folder name ;[x][1]=nested array (same as this, starting at [x][0] folder) ;[x][2]=size (recursive) of folder #region private Func __ArrayNGetDirTree($sPath, $fMin, $fMax) Local $hSearch = FileFindFirstFile($sPath & '\*'), $aFolder[100][3] $aFolder[0][0] = 0 $aFolder[0][1] = $sPath $aFolder[0][2] = 0 ;Search for files and folders, record folders in array, sum up file sizes If $hSearch <> -1 Then $sFilename = FileFindNextFile($hSearch) While Not @error If _FileIsDir($sPath & '\' & $sFilename) Then If $sFileName <> '.' And $sFileName <> '..' Then $aFolder[0][0] += 1 If $aFolder[0][0] >= UBound($aFolder, 1) Then ReDim $aFolder[$aFolder[0][0] * 2][3] $aFolder[$aFolder[0][0]][0] = $sFileName EndIf Else $aFolder[0][2] += FileGetSize($sPath & '\' & $sFilename) EndIf $sFilename = FileFindNextFile($hSearch) WEnd EndIf FileClose($hSearch) ;loop through folder list, get recursive If $aFolder[0][0] Then Local $fSlice = $fMax / $aFolder[0][0], $fCur For $i = 1 To $aFolder[0][0] $fCur = $fMin + $i * $fSlice _ProgressUpdate($fCur, $aFolder[$i][0], _FileTruncPath($sPath,42)) $aFolder[$i][1] = __ArrayNGetDirTree($sPath & '\' & $aFolder[$i][0], $fCur, $fSlice) $aFolder[$i][2] = @extended $aFolder[0][2] += $aFolder[$i][2] Next EndIf ;trim final array, set extended to the total file size, return the array ReDim $aFolder[$aFolder[0][0] + 1][3] SetExtended($aFolder[0][2]) Return $aFolder EndFunc #endregion Func _ArrayNGetDirTree($sPath, $sProgressTitle = @ScriptName) _ProgressCreate('Scanning Folders...','',$sProgressTitle) $aRet = __ArrayNGetDirTree($sPath, 0, 100) _ProgressDelete() Return $aRet EndFuncIt uses my Multi-level Progress Bars, so either get those or comment out the lines calling _Progress*(), or convert them over to the built-in progress bars.It uses some supporting functions:expandcollapse popup;=============================================================================== ; ; 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 0 EndFunc ;==>_FileIsDir ;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 EndFuncThen the code to export to XML:;Takes the return of _ArrayNGetTree and writes it to an XML file #region Private Func __ArrayNDirTreeToXML(ByRef $aTree, $sPath, $iLevel, $hFile, $fMin, $fMax) Local $sPrefix = _StringRepeat(@Tab, $iLevel), $i FileWrite($hFile, $sPreFix & '<folder name="' & $sPath & '" size="' & $aTree[0][2]) If $aTree[0][0] > 0 Then Local $fSlice = $fMax / $aTree[0][0], $fCur FileWriteLine($hFile, '" >') For $i = 1 to $aTree[0][0] $fCur = $fMin + $i * $fSlice __ArrayNDirTreeToXML($aTree[$i][1], $aTree[$i][0], $iLevel + 1, $hFile, $fCur, $fSlice) _ProgressUpdate($fCur, $aTree[$i][0]) Next FileWriteLine($hFile, $sPreFix & '</folder>') Else FileWriteLine($hFile, '" />') EndIf EndFunc #endregion Func _ArrayNDirTreeToXML(ByRef $aTree, $sFilename, $sHeader='') _ProgressCreate('Writing to XML...','',@ScriptName) Local $hOutFile = FileOpen($sFilename, 2) If $hOutFile <> -1 Then If $sHeader Then FileWrite($hOutFile, $sHeader) __ArrayNDirTreeToXml($aTree, $aTree[0][1], 0, $hOutFile, 0, 100) FileClose($hOutFile) EndIf _ProgressDelete() EndFuncand a sample of how to use it:$anMyDocs = _ArrayNGetDirTree(@MyDocumentsDir) _ArrayNDirTreeToXML($anMyDocs, 'MyDocs.xml') Run(@ComSpec & ' /c start DirSizes.xml')If you use IE to view XML, it will pop up and give you a security warning. It's kind of stupid, because it's warning you about IE's own code to view XML. Click yes and everything will be fine, or if you're paranoid click no and you'll still be able to view the xml, just won't be able to expand/collapse the branches.Anyway, I think that this routine is very useful for anyone who is trying to figure out where all their HD space keeps going.... 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...
randallc Posted August 6, 2005 Share Posted August 6, 2005 hi,Looks good;your example needs #include <String.au3>I think?Best, randall ExcelCOM... AccessCom.. Word2... FileListToArrayNew...SearchMiner... Regexps...SQL...Explorer...Array2D.. _GUIListView...array problem...APITailRW 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