
close
close
When working with results from a PowerShell expression, you may find it helpful to group objects by a common property. There are a few ways you can group objects depending on what you want to accomplish. Sometimes you need to work with each set of like objects, and sometimes you want to simply view the results. Let me share a few PowerShell examples and techniques to help you get the most out of group PowerShell results.
The most important thing to know about grouping is that you are working with objects and the grouping is almost always based on some common property. Thus, there is an assumption that you are grouping like objects. Sure, you could group different types of objects, but this is going to be an awkward process. The grouping property technically doesn’t have to have a value. You can use any property that you see with Get-Member. As I’ll demonstrate, you can even group on a dynamic or custom property of your own design. The cmdlet we’ll start with is Group-Object.
Let’s start with an example of something that everyone can run, and something you might even find practical. All event log entries have a source property. How did I know? I asked PowerShell.
advertisment
get-eventlog system -newest 1 | select *
Obtaining the source property with the get-eventlog cmdlet in PowerShell. (Image Credit: Jeff Hicks)
get-eventlog system | group-object -Property source
Grouping objects on the property in PowerShell. (Image Credit: Jeff Hicks)
advertisment
get-eventlog system -newest 10 | group-object -Property source | get-member
I only selected a few entries to speed things up.
Using Get-Member in Windows PowerShell. (Image Credit: Jeff Hicks)
get-eventlog system | group-object -Property source -NoElement | Sort Count -Descending | Select -first 10
I don’t care about the individual entries, so I’m including the –NoElement parameter with Group-Object, which leaves the Name and Count properties.
Using the NoElement property with Group-Object in Windows PowerShell. (Image Credit: Jeff Hicks)
advertisment
get-eventlog system | group-object -Property source -NoElement | Sort Count -Descending | Select -first 10 | format-table -autosize
Formatting the output to be more readable. (Image Credit: Jeff Hicks)
$g = dir c:\scripts -Recurse -File | group Extension
Sorting by extension in Windows PowerShell. (Image Credit: Jeff Hicks)
$g | foreach {[pscustomobject]@{Type=$_.Name;Count=$_.Count;Average = ($_.group | measure-object Length -Average).average}} | sort Average -descending | out-Gridview -title Averages
Using ForEach-Object, I’m creating a custom object with a property called Type, which will use the Name property of each group object, the Count property, and a custom property that takes the group of files and measures their average size.
Measuring a group of files’ average size. (Image Credit: Jeff Hicks)
$g.where({$_.name -match "psm1"})
I think a better approach is to create a hashtable.
$h = dir c:\scripts -Recurse -File | group Extension -AsHashTable
With a hashtable, each name becomes a key. You can treat the key like a property name and the value will be the collection of grouped objects. But there is a slight hiccup with what I’ve just created. Look at what I have to do to access one of my new properties.
It becomes more difficult to access my properties. (Image Credit: Jeff Hicks)
An alternative method of accessing properties. (Image Credit: Jeff Hicks)
$j = dir c:\scripts -Recurse -File | where {$_.extension} | group {$_.Extension.substring(1)} –AsHashTable -AsString
I had to filter out files with no extension to avoid errors creating a hashtable with null keys. Or I could have used PowerShell to insert something for files with no extensions. I can insert as much code as I need into the scriptblock, using $_ to reference each object in the pipeline.
Here’s a big warning based on my experience: If you are using a custom property, then you should also include the AsString parameter, which will force PowerShell to turn each key into a string.
Here’s what I end up with:
Now it is much easier to access specific entries.
Now we have an easier way to access entries. (Image Credit: Jeff Hicks)
$data = $j.GetEnumerator() | foreach {[pscustomobject]@{Type=$_.key;Count=$_.value.count;Size=($_.Value | measure length -sum).sum}}
Processing data in the hashtable. (Image Credit: Jeff Hicks)
Get-aduser –filter "department –like '*'" –properties Department,Title | Group Department
Grouping Active Directory objects on the department property. (Image Credit: Jeff Hicks)
More in PowerShell
Microsoft’s New PowerShell Crescendo Tool Facilitates Native Command-Line Wraps
Mar 21, 2022 | Rabia Noureen
Most popular on petri