· 7 years ago · Oct 29, 2018, 07:42 PM
1<#
2.SYNOPSIS
3 Get folder sizes in specified tree.
4.DESCRIPTION
5 Script creates an HTML report with owner information, when created,
6 when last updated and folder size. By default script will only do 1
7 level of folders. Use Recurse to do all sub-folders.
8
9 Update the PARAM section to match your environment.
10.PARAMETER Paths
11 Specify the path(s) you wish to report on. Specify an array of paths for
12 mulitple folders to be processed, or pipe folders in.
13.PARAMETER ReportPath
14 Specify where you want the HTML report to be saved
15.PARAMETER Sort
16 Specify which column you want the script to sort by.
17
18 Valid colums are:
19 Folder Sort by folder name
20 Size Sort by folder size, largest to smallest
21 Created Sort by the Created On column
22 Changed Sort by the Last Updated column
23 Owner Sort by Owner
24.PARAMETER Descending
25 Switch to control how you want things sorted. By default the script
26 will sort in an ascending order. Use this switch to reverse that.
27.PARAMETER Recurse
28 Report on all sub-folders
29.EXAMPLE
30 .\Get-FolderSizes
31
32 Run script and use defaults
33.EXAMPLE
34 .\Get-FolderSizes -Path "c:\Windows" -ReportPath "c:\Scripts"
35
36 Run the script and report on all folers in C:\Windows. Save the
37 HTML report in C:\Scripts
38.EXAMPLE
39 .\Get-FolderSizes -Path "c:\Windows" -ReportPath "c:\Scripts" -Recurse
40
41 Run the script and report on all folers in C:\Windows. Save the
42 HTML report in C:\Scripts. Report on all sub-folders.
43.OUTPUTS
44 FolderSizes.HTML in specified Report Path
45.NOTES
46 Author: Martin Pugh
47 Twitter: @thesurlyadm1n
48 Spiceworks: Martin9700
49 Blog: www.thesurlyadmin.com
50
51 Changelog:
52 1.6 Added some error trapping to test if the path provided is valid.
53 1.5 Added ability to process multiple paths, both from array input as well as
54 from the pipeline. Added verbose logging. Also switched away from using
55 the COM Object. While the COM object is much faster, it will return 0 if
56 it has any problem in the folder structure (such as a typical access denied
57 when running against C:\Windows). I figure SOME result is better than none.
58 Tightened up the final report so it looks a little better.
59 1.41 @SPadminWV found a bug in the Total Size reporting.
60 1.4 Add Sort and descending parameter
61 1.3 Added Recurse parameter, default behavior is to now do 1 level of folders,
62 recurse will do all sub-folders.
63 1.2 Added function to make the rows in the table alternating colors
64 1.1 Updated to use COM Object Scripting.FileSystemObject which
65 should increase performance. Inspired by MS Scripting Guy
66 Ed Wilson.
67 1.0 Initial Release
68.LINK
69 http://community.spiceworks.com/scripts/show/1738-get-foldersizes
70.LINK
71 http://community.spiceworks.com/topic/286820-how-to-export-list-all-folders-from-drive-the-list-should-include
72.LINK
73 http://blogs.technet.com/b/heyscriptingguy/archive/2013/01/05/weekend-scripter-sorting-folders-by-size.aspx
74#>
75#requires -Version 3.0
76[CmdletBinding()]
77Param (
78 [Parameter(ValueFromPipeline)]
79 [string[]]$Paths = "c:\dropbox\test",
80 [string]$ReportPath = "c:\dropbox\test",
81 [ValidateSet("Folder","Folders","Size","Created","Changed","Owner")]
82 [string]$Sort = "Folder",
83 [switch]$Descending,
84 [switch]$Recurse
85)
86
87Begin {
88 Function AddObject {
89 Param (
90 $FileObject
91 )
92 $RawSize = (Get-ChildItem $FileObject.FullName -Recurse | Measure-Object Length -Sum).Sum
93
94 If ($RawSize)
95 { $Size = CalculateSize $RawSize
96 }
97 Else
98 { $Size = "0.00 MB"
99 }
100 $Object = New-Object PSObject -Property @{
101 'Folder Name' = $FileObject.FullName
102 'Created on' = $FileObject.CreationTime
103 'Last Updated' = $FileObject.LastWriteTime
104 Size = $Size
105 Owner = (Get-Acl $FileObject.FullName).Owner
106 RawSize = $RawSize
107 }
108 Return $Object
109 }
110
111 Function CalculateSize {
112 Param (
113 [double]$Size
114 )
115 If ($Size -gt 1000000000)
116 { $ReturnSize = "{0:N2} GB" -f ($Size / 1GB)
117 }
118 Else
119 { $ReturnSize = "{0:N2} MB" -f ($Size / 1MB)
120 }
121 Return $ReturnSize
122 }
123
124 Function Set-AlternatingRows {
125 [CmdletBinding()]
126 Param(
127 [Parameter(Mandatory=$True,ValueFromPipeline=$True)]
128 [object[]]$Lines,
129
130 [Parameter(Mandatory=$True)]
131 [string]$CSSEvenClass,
132
133 [Parameter(Mandatory=$True)]
134 [string]$CSSOddClass
135 )
136 Begin {
137 $ClassName = $CSSEvenClass
138 }
139 Process {
140 ForEach ($Line in $Lines)
141 { $Line = $Line.Replace("<tr>","<tr class=""$ClassName"">")
142 If ($ClassName -eq $CSSEvenClass)
143 { $ClassName = $CSSOddClass
144 }
145 Else
146 { $ClassName = $CSSEvenClass
147 }
148 Return $Line
149 }
150 }
151 }
152
153 #Validate sort parameter
154 Switch -regex ($Sort)
155 { "^folder.?$" { $SortBy = "Folder Name";Break }
156 "created" { $SortBy = "Created On";Break }
157 "changed" { $SortBy = "Last Updated";Break }
158 default { $SortBy = $Sort }
159 }
160
161 $Report = @()
162 $TotalSize = 0
163 $NumDirs = 0
164 $Title = @()
165 Write-Verbose "$(Get-Date): Script begins!"
166}
167
168Process {
169 ForEach ($Path in $Paths)
170 { #Test if path exists
171 If (-not (Test-Path $Path))
172 { $Result += $Object = New-Object PSObject -Property @{
173 'Folder Name' = $Path
174 'Created on' = ""
175 'Last Updated' = ""
176 Size = ""
177 Owner = "Path not found"
178 RawSize = 0
179 }
180 $Title += $Path
181 Continue
182 }
183
184 #First get the properties of the starting path
185 $NumDirs ++
186 Write-Verbose "$(Get-Date): Now working on $Path..."
187 $Root = Get-Item -Path $Path
188 $Result = AddObject $Root
189 $TotalSize += $Result.RawSize
190 $Report += $Result
191 $Title += $Path
192
193 #Now loop through all the subfolders
194 $ParamSplat = @{
195 Path = $Path
196 Recurse = $Recurse
197 }
198 ForEach ($Folder in (Get-ChildItem @ParamSplat | Where { $_.PSisContainer }))
199 { $Report += AddObject $Folder
200 $NumDirs ++
201 }
202 }
203}
204
205End {
206 #Create the HTML for our report
207 $Header = @"
208<style>
209TABLE {border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
210TH {border-width: 1px;padding: 3px;border-style: solid;border-color: black;background-color: #6495ED;}
211TD {border-width: 1px;padding: 3px;border-style: solid;border-color: black;}
212.odd { background-color:#ffffff; }
213.even { background-color:#dddddd; }
214</style>
215<Title>
216Folder Sizes for "$Path"
217</Title>
218"@
219
220 $TotalSize = CalculateSize $TotalSize
221
222 $Pre = "<h1>Folder Sizes Report</h1><h3>Folders processed: ""$($Title -join ", ")""</h3>"
223 $Post = "<h2><p>Total Folders Processed: $NumDirs<br>Total Space Used: $TotalSize</p></h2>Run on $(Get-Date -f 'MM/dd/yyyy hh:mm:ss tt')</body></html>"
224
225 #Create the report and save it to a file
226 $HTML = $Report | Select 'Folder Name',Owner,'Created On','Last Updated',Size | Sort $SortBy -Descending:$Descending | ConvertTo-Html -PreContent $Pre -PostContent $Post -Head $Header | Set-AlternatingRows -CSSEvenClass even -CSSOddClass odd | Out-File $ReportPath\FolderSizes.html
227
228 #Display the report in your default browser
229 & $ReportPath\FolderSizes.html
230
231 Write-Verbose "$(Get-Date): $NumDirs folders processed"
232 Write-Verbose "$(Get-Date): Script completed!"
233}