What we are really after is sorting the output first and then grouping it. The Sort-Object cmdlet does exactly what its name implies - it sorts objects based on property values.
PS C:\> get-process|sort-object handles Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 0 0 0 16 0 0 Idle 21 1 168 376 4 0.46 776 smss 30 2 1912 2436 29 0.11 1288 cmd 34 2 400 1524 15 0.21 2664 WLTRYSVC 43 2 376 1392 13 0.18 2932 MsPMSPSv 62 3 1820 4404 34 0.21 1456 ApntEx 64 3 1744 5628 37 0.24 324 notepad 65 2 1472 1600 14 0.17 2488 wdfmgr 69 3 632 2044 13 0.10 1580 sqlbrowser 72 3 828 2428 27 0.33 1208 scardsvr 76 2 524 2116 19 0.04 828 avgupsvc 91 5 1284 3184 29 2.16 300 svchost 95 4 1528 5852 39 0.83 844 sqlmangr ...
Here we've taken the output of Get-Process and sorted it by the handles property. The default sort is ascending, but if you prefer the cmdlet includes a -descending parameter:
PS C:\> get-process|sort-object handles -descending Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 1290 49 14000 23608 127 38.52 1892 svchost 1076 0 0 220 2 47.18 4 System 817 78 15856 8436 136 15.55 1628 Groove 706 7 1888 4880 28 18.51 868 csrss 616 16 25680 41096 127 100.01 484 explorer 589 12 8076 1508 62 3.24 892 winlogon 538 11 15508 8864 95 126.88 1948 Smc 483 20 38092 63020 223 168.63 2308 WINWORD ...
Let's return to our earlier example in which we tried to group the output of Get-Service by status. Now we can pipe the Get-Service cmdlet to Sort-Object, specifying primary sort on status, then on name. Next we send the object to Format-Table and group by status. Here's the output we get:
PS C:\> get-service|sort-object status,name |format-table ` >>-groupby status >> Status: Stopped Status Name DisplayName ------ ---- ----------- Stopped Alerter Alerter Stopped ALG Application Layer Gateway Service Stopped AppMgmt Application Management Stopped aspnet_state ASP.NET State Service Stopped BAsfIpM Broadcom ASF IP monitoring service ... Stopped BITS Background Intelligent Transfer Ser... Stopped Browser Computer Browser Stopped CiSvc Indexing Service ... Status: Running Status Name DisplayName ------ ---- ----------- Running AudioSrv Windows Audio Running Avg7Alrt AVG7 Alert Manager Server Running Avg7UpdSvc AVG7 Update Service Running AVGEMS AVG E-mail Scanner Running CryptSvc Cryptographic Services Running DcomLaunch DCOM Server Process Launcher Running Dhcp DHCP Client Running Dnscache DNS Client Running Eventlog Event Log Running EventSystem COM+ Event System Running IISADMIN IIS Admin Running lanmanserver Server Running lanmanworkstation Workstation ... PS C:\>
Again, we've edited the output for brevity, but you get the picture.
One final Sort-Object parameter is -Unique, which not only gives sorted output, but it also displays only the unique values:
PS C:\> $var=@(7,3,4,4,4,2,5,5,4,8,43,54) PS C:\> $var|sort 2 3 4 4 4 4 5 5 7 8 43 54 PS C:\> $var|sort -unique 2 3 4 5 7 8 43 54 PS C:\>
We've defined an array of numbers and first pipe it through a regular Sort-Object cmdlet. Compare that to the second expression that uses - Unique. Now the output is sorted and only unique objects are returned.
Alias Alert
You will probably find it easier to use the alias for Sort-Object, which is Sort, as we did in the last example.
PowerShell also has a Get-Unique cmdlet that functions essentially the same as Sort -Unique, but without the sorting feature. Here's the array we just used piped through Get-Unique:
PS C:\> $var|get-unique 7 3 4 2 5 4 8 43 54 PS C:\>