Get-Process|Get-Member $_
, why doesn't this work? If$_
represents current object in pipeline, shouldn't the above output be returning members of each process object?- Will a cmdlet pipeline all its output objects at once to the next cmdlet or as and when there is an object available?
- As #1 does not work, when exactly can I use
$_
variable? The conditions under which this variable gets created will be more helpful rather than just a cmdlet example to demonstrate the use of$_
.
2 Answers
$_
is an automatic variable that is available for use within the scriptblock input of certain cmdlets to represent the current item in the pipeline.
Get-Process | Get-Member $_
doesn't work because you send the pipeline object in to Get-Member
via the |
, but you then don't have any way to access the internals of Get-Member
.
You could do this:
Get-Process | ForEach-Object {
$_ | Get-Member
}
You would then get a Get-Member
output for every item in the collection of objects output by Get-Process
, although this would be redundant as each would be the same.
Cmdlets do send the objects down the pipeline one at a time. You can see that with this example:
Get-Process | ForEach-Object {
$_
Start-Sleep 1
}
You can see with the added delay that the results are arriving in the ForEach-Object
one at a time as soon as they are available.
Other places you can use the $_
variable are in Where-Object
and Select-Object
. For example:
Get-Process | Where-Object { $_.name -like 'win*' }
Here the Where-Object
cmdlet is taking each item of the pipeline and we're using $_
to access the name property of that item to see if it's like the string win
. If it is, then it gets sent onwards (and so comes out to the console) if it's not, Where-Object
discards it.
You can use $_
in a Select-Object
when doing calculated properties. For example:
Get-Process | Select-Object name,@{N='WorkingSetGB';E={$_.WorkingSet / 1GB}}
Here we use $_
to get at the WorkingSet
property of each item and then convert it to a GB value by using / 1GB
.
Yes, $_
represents the current object in the pipeline but since Get-Member takes a pipeline input you just have to pipe the result to the cmdlet:
Get-Process | Get-Member
Another example is
Get-Process | Export-Csv MyFile.csv
Here again, $_ is not needed, because Export-Csv takes pipeline input, and receives the output of Get-Process, one process at a time, through the pipeline. There is a loop inside the implementation of Export-csv, but that need not concern you here.
You typically use $_
when you pipe an object to the ForEach-Object
cmdlet:
Get-Process | ForEach-Object {
Write-Host $_.Name
}
get-help about_pipelines