As I usually do, I was helping out in the forums at ScriptingAnswers.com. A member had several variables that he wanted to show as a group. As is almost always the case, the answer in PowerShell is object. I talk about this all the time in classes, conferences and online chitchat. Let me offer up a script that demonstrates how objects are the answer.
My business need was to report on files found in a given folder or path. I wanted to get a breakdown of file types showing me the number of each type, their total size and their percentage of all files by count and size.
|
|
<span style="color: #006400;">#requires -version 2.0</span> <span style="color: #00008b;">Param</span><span style="color: #000000;">(</span><span style="color: #008080;">[string]</span><span style="color: #ff4500;">$path</span><span style="color: #a9a9a9;">=</span><span style="color: #8b0000;">"$env:userprofile\documents"</span><span style="color: #000000;">)</span> <span style="color: #00008b;">if</span> <span style="color: #000000;">(</span><span style="color: #0000ff;">Test-Path</span> <span style="color: #000080;">-path</span> <span style="color: #ff4500;">$path</span><span style="color: #000000;">)</span> <span style="color: #000000;">{</span> <span style="color: #0000ff;">write-host</span> <span style="color: #8b0000;">"Collecting file information for $path"</span> ` |
|
|
<span style="color: #000080;">-ForegroundColor</span> <span style="color: #8a2be2;">Green</span> <span style="color: #ff4500;">$files</span><span style="color: #a9a9a9;">=</span><span style="color: #0000ff;">dir</span> <span style="color: #ff4500;">$path</span> <span style="color: #000080;">-recurse</span> <span style="color: #000080;">-errorAction</span> <span style="color: #8b0000;">"SilentlyContinue"</span> <span style="color: #a9a9a9;">|</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
<span style="color: #0000ff;">where</span> <span style="color: #000000;">{</span><span style="color: #a9a9a9;">-not</span> <span style="color: #ff4500;">$_</span><span style="color: #a9a9a9;">.</span><span style="color: #000000;">PSIsContainer</span><span style="color: #000000;">}</span> <span style="color: #ff4500;">$stats</span><span style="color: #a9a9a9;">=</span><span style="color: #ff4500;">$files</span> <span style="color: #a9a9a9;">|</span> <span style="color: #0000ff;">Measure-Object</span> <span style="color: #000080;">-Property</span> <span style="color: #8a2be2;">Length</span> <span style="color: #000080;">-sum</span> <span style="color: #ff4500;">$grouped</span><span style="color: #a9a9a9;">=</span><span style="color: #ff4500;">$files</span> <span style="color: #a9a9a9;">|</span> <span style="color: #0000ff;">group</span> <span style="color: #000080;">-property</span> <span style="color: #8a2be2;">Extension</span> <span style="color: #00008b;">foreach</span> <span style="color: #000000;">(</span><span style="color: #ff4500;">$group</span> <span style="color: #00008b;">in</span> <span style="color: #ff4500;">$grouped</span><span style="color: #000000;">)</span> <span style="color: #000000;">{</span> <span style="color: #006400;">#measure the total size of each file type</span> <span style="color: #ff4500;">$measure</span><span style="color: #a9a9a9;">=</span><span style="color: #ff4500;">$group</span><span style="color: #a9a9a9;">.</span><span style="color: #000000;">group</span> <span style="color: #a9a9a9;">|</span> <span style="color: #0000ff;">measure-object</span> <span style="color: #000080;">-Property</span> <span style="color: #8a2be2;">length</span> <span style="color: #000080;">-sum</span> <span style="color: #006400;">#calculate % of total size</span> <span style="color: #ff4500;">$perSize</span><span style="color: #a9a9a9;">=</span><span style="color: #8b0000;">"{0:P4}"</span> <span style="color: #a9a9a9;">-f</span> <span style="color: #000000;">(</span><span style="color: #ff4500;">$measure</span><span style="color: #a9a9a9;">.</span><span style="color: #000000;">sum</span><span style="color: #a9a9a9;">/</span><span style="color: #ff4500;">$stats</span><span style="color: #a9a9a9;">.</span><span style="color: #000000;">sum</span><span style="color: #000000;">)</span> <span style="color: #006400;">#calculate % of total number</span> <span style="color: #ff4500;">$perTotal</span><span style="color: #a9a9a9;">=</span><span style="color: #8b0000;">"{0:P4}"</span> <span style="color: #a9a9a9;">-f</span> <span style="color: #000000;">(</span><span style="color: #ff4500;">$measure</span><span style="color: #a9a9a9;">.</span><span style="color: #000000;">count</span><span style="color: #a9a9a9;">/</span><span style="color: #ff4500;">$stats</span><span style="color: #a9a9a9;">.</span><span style="color: #000000;">count</span><span style="color: #000000;">)</span> <span style="color: #006400;">#write a custom object to the pipeline</span> <span style="color: #0000ff;">new-object</span> <span style="color: #8a2be2;">psobject</span> <span style="color: #000080;">-Property</span> <span style="color: #000000;">@{</span> <span style="color: #000000;">Extension</span><span style="color: #a9a9a9;">=</span><span style="color: #ff4500;">$group</span><span style="color: #a9a9a9;">.</span><span style="color: #000000;">name</span> <span style="color: #000000;">Total</span><span style="color: #a9a9a9;">=</span><span style="color: #ff4500;">$group</span><span style="color: #a9a9a9;">.</span><span style="color: #000000;">count</span> <span style="color: #000000;">TotalSizeMB</span><span style="color: #a9a9a9;">=</span><span style="color: #008080;">[Math]</span><span style="color: #a9a9a9;">::</span><span style="color: #000000;">Round</span><span style="color: #000000;">(</span><span style="color: #ff4500;">$measure</span><span style="color: #a9a9a9;">.</span><span style="color: #000000;">sum</span><span style="color: #a9a9a9;">/</span><span style="color: #800080;">1mb</span><span style="color: #a9a9a9;">,</span><span style="color: #800080;">2</span><span style="color: #000000;">)</span> <span style="color: #000000;">PercentTotal</span><span style="color: #a9a9a9;">=</span><span style="color: #ff4500;">$perTotal</span> <span style="color: #000000;">PercentSize</span><span style="color: #a9a9a9;">=</span><span style="color: #ff4500;">$perSize</span> <span style="color: #000000;">Files</span><span style="color: #a9a9a9;">=</span><span style="color: #ff4500;">$group</span><span style="color: #a9a9a9;">.</span><span style="color: #000000;">group</span> <span style="color: #000000;">}</span> <span style="color: #000000;">}</span> <span style="color: #006400;">#foreach</span> <span style="color: #000000;">}</span> <span style="color: #006400;">#if test-path</span> <span style="color: #00008b;">else</span> <span style="color: #000000;">{</span> <span style="color: #0000ff;">Write-Warning</span> <span style="color: #8b0000;">"Failed to find $path"</span> <span style="color: #000000;">}</span> |
The script takes a path as a parameter but defaults to your documents folder. Get-Childitem retrieves all files. I’m setting the –errorAction parameter to silentlycontinue to avoid the annoying error messages you get when trying to read protected system folders. The collection of files are then grouped by extension. Each group is then analyzed.
At this point I have a number of pieces of information to display. In a VBScript I would have most like written some message to the screen for each file type. Technically I could do the same thing here but why? Using New-Object I create a new object with properties for all my data. The objects written to the pipeline can be manipulated just like any other object. Let me check my C: drive.
PS C:\> $c=c:\scripts\filestats.ps1 “c:\”
Hmmm…how many different file types are on my computer?
PS C:\> $c.count
1897
Which file types are taking the most space?
PS C:\> $c | sort totalsizeMB -desc | select -first 10 -property * -ExcludeProperty Files | format-table -auto
TotalSizeMB PercentTotal Total Extension PercentSize
———– ———— —– ——— ———–
115692.94 0.0637 % 90 .vmdk 57.8050 %
19559.24 0.0219 % 31 .iso 9.7726 %
14375.12 0.0014 % 2 .vdi 7.1824 %
12440.64 14.8798 % 21018 .dll 6.2159 %
6972.15 2.4778 % 3500 .exe 3.4836 %
6190.48 0.0064 % 9 .wim 3.0930 %
2884.98 0.1373 % 194 .CAB 1.4415 %
2672.56 0.0021 % 3 .m4v 1.3353 %
1424.91 0.0042 % 6 .sav 0.7119 %
1202.12 0.0092 % 13 .mp4 0.6006 %
My custom object even includes a property, files, which itself is a collection of objects. For example, what are the .vdi files?
PS C:\> $c | where {$_.extension -eq “.vdi”} | select -ExpandProperty Files
Directory: C:\VirtualBox\Exchange
Mode LastWriteTime Length Name
—- ————- —— —-
-a— 6/29/2010 1:58 PM 1507336243 ExchangeHDD.vdi
Directory: C:\VirtualBox\R2
Mode LastWriteTime Length Name
—- ————- —— —-
-a— 6/21/2010 9:34 PM 41472 ExchangeStore.vdi
The bottom line is that having objects offers tremendous possibilities. So the next time you’re working on a PowerShell problem, know that objects are the answer.
My script was intended as a demonstration but if you’d like a copy
Like this:
Like Loading...