Prof. Powershell
Where Do You Want to Go Today?
Too much information! Make it less complicated with the Where-Object cmdlet.
- By Jeffery Hicks
- 07/09/2008
Powershell's object richness sometimes leads to an overabundance of information. Some cmdlets support the -filter parameter, which will limit the amount of information coming down the pipeline. But for cmdlets that lack that parameter or where you might need more complex filtering, we have the Where-Object cmdlet. You'll most likely see it used with its alias, Where, as in this:
PS C:\> get-service | where {$_.status -eq "stopped"} | Select DisplayName
The Get-Service cmdlet executes and writes service objects to the pipeline. Remember these are objects as verified by piping Get-Service to Get-Member (see Fig. 1).
(Click image to view larger version.) |
Figure 1. Results of Where-Object. |
The Where-Object cmdlet evaluates a filter script that is enclosed in a set of curly braces. The filter script can be as simple or as complex as necessary. Mine is pretty simple; the filter says, "keep objects where the status property of the current object in the pipeline is equal to 'stopped'." If the expression is true, the object is passed down the pipeline, in this example to the Select-Object cmdlet.
What confuses many people until they get their heads around PowerShell's object-nature is the $_ symbol. The $_ symbol is a placeholder for the current object in the pipeline. Here's what is happening on my computer (see Fig. 2): Get-Service will send a group of objects down the pipeline to Where-Object. On my computer, the first object is for the AcrSch2Svc service, which I know is stopped.
(Click image to view larger version.) |
Figure 2. My computer is just a happenin' place... |
The Where-Object cmdlet looks at the object, checks the Status property and, since it has a value of Stopped, the object is kept in the pipeline. The next service object for the AeLookupSvc is running so the filter script evaluates as False. The object is discarded from the pipeline. This process is repeated until all service objects in the pipeline have been evaluated.
You can have complex expressions as well like this:
PS C:\> get-process | where {$_.workingset -gt 4mb -and $_.workingset -lt 5mb}
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
478 5 1632 5084 85 0.66 584 csrss
60 3 1244 4156 38 0.22 1528 ehmsas
81 3 2556 4412 51 0.06 2940 FJSSDMN
77 3 2372 4136 41 0.03 3804 FUJ02E3
78 3 1644 4712 49 0.05 3280 hkcmd
63 3 1264 4164 36 0.05 1040 igfxext
74 3 1552 4828 38 0.94 3220 igfxsrvc
251 5 1556 4348 65 0.20 1124 LVPrcSrv
65 3 1264 4244 44 0.02 1184 prevhost
311 6 5916 4396 64 13.48 5112 SearchProtocolHost
122 3 1964 4780 36 0.09 1252 svchost
100 4 1472 4136 36 0.28 624 wininit
This expression is filtering out process objects that don't have a working set size between 4MB and 5MB. For more information and examples, look at the help for Where-Object as well as the About files for operators:
PS C:\> help *operator*
Use the Where-Object cmdlet prudently and it will get you far.
About the Author
Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, trainer and consultant. Jeff has written for numerous online sites and print publications, is a contributing editor at Petri.com, and a frequent speaker at technology conferences and user groups.