Using $_

Tags:
The $_ symbol seems to be causing confusion from some recent forum questions I’ve seen.
$_ represents the current object on the pipeline – if you want to know why $_ was chosen you’ll have to read PowerShell in Action!
You can use $_ in a number of situations – in commands that perform an action on every object (or selected objects) on the pipeline. Here’s some of the commoner usages:
In the early versions of PowerShell you used it in the filter script of Where-Object
Get-Process | Where-Object -FilterScript {$_.CPU -gt 50}
This is more usually written as
Get-Process | Where {$_.CPU -gt 50}
As of PowerShell v3 if you are filtering on ONE property you can simplify the syntax
Get-Process | Where CPU -gt 50
which is a truncated version of
Get-Process | Where -Property CPU -gt -Value 50
When you write it like this its obvious what is happening. Get in the habit of thinking of the syntax in this manner even if you write in the shortened form
If you need to filter on TWO or more properties you have to use the old style syntax
Get-Process | Where {$_.CPU -gt 50 -AND $_.Handles -gt 1000}
In all of these cases you’re comparing a property of the current pipeline object against a value. If the comparison is true the object is passed onto the next step of the pipeline. If its false the object is discarded.
You can use $psitem in place of $_ if you prefer
Get-Process | Where {$psitem.CPU -gt 50}
In the Foreach-Object cmdlet you can use $_ to refer to the current object
Get-CimInstance -ClassName Win32_NetworkAdapter -Filter "NetEnabled = $true" | ForEach-Object { $ip = Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter "Index = $($_.DeviceId)" $props = @{ Name = $_.NetConnectionId Product = $_.ProductName DHCP = $ip.DHCPEnabled IP = $ip.IPAddress } New-Object -TypeName PSObject -Property $props }
$psitem also works in this situation
The third common usage of $_ is in select-object in calculated fields (you can do the same in Format-Table)
Get-CimInstance -ClassName Win32_LOgicalDisk -Filter "DriveType=3" | select DeviceId, VolumeName, @{N='Size(GB)'; E={[math]::Round($_.Size / 1GB, 2)}}, @{N='Used(GB)'; E={[math]::Round(($_.Size - $_.FreeSpace) / 1GB, 2)}}, @{N='Free(%)'; E={[math]::Round(($_.FreeSpace / $_.Size) * 100, 2 )}}
In this example we’re changing the size to GB from bytes and calculating the used space and the % free space. Again you could use $psitem instead of $_
ONE PLACE YOU CAN’T USE $_ IS IN A FOREACH LOOP
This fails
$nics = Get-CimInstance -ClassName Win32_NetworkAdapter -Filter "NetEnabled = $true" $data = foreach ($nic in $nics) { $ip = Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter "Index = $($_.DeviceId)" $props = @{ Name = $_.NetConnectionId Product = $_.ProductName DHCP = $ip.DHCPEnabled IP = $ip.IPAddress } New-Object -TypeName PSObject -Property $props } $data |Format-List
To recap $_ (or $psitem) is used to represent the current object on the pipeline. You can us it in commands that are performing an action on every object on the pipeline.
 Comment on this Post