Prof. Powershell

Where Do You Want to Go Today?

Too much information! Make it less complicated with the Where-Object cmdlet.

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).

Oh, Brother Where Art Thou? (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.

My Computer Computes(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.

comments powered by Disqus
Most   Popular