297

I've seen the following a lot in PowerShell, but what does it do exactly?

$_
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Micah
  • 111,873
  • 86
  • 233
  • 325
  • 11
    The question has, of course, been answered for the single special token given, but for a wallchart illustrating _all_ of PowerShell's special tokens, take a look at [The Complete Guide to PowerShell Punctuation](https://www.simple-talk.com/sysadmin/powershell/the-complete-guide-to-powershell-punctuation/) – Michael Sorens Nov 16 '16 at 22:04
  • As of this writing, the official description of the [automatic $_ variable](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Automatic_Variables#_) (whose alias is `$PSItem`) is unfortunately terse. See also the bottom section of [this answer](https://stackoverflow.com/a/55667981/45375), which tries to provide a systematic overview of all contexts in which `$_` / `$PSItem` is meaningfully defined. – mklement0 Dec 04 '22 at 22:25

7 Answers7

216

This is the variable for the current value in the pipe line, which is called $PSItem in Powershell 3 and newer.

1,2,3 | %{ write-host $_ } 

or

1,2,3 | %{ write-host $PSItem } 

For example in the above code the %{} block is called for every value in the array. The $_ or $PSItem variable will contain the current value.

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 55
    It's not necessarily related to the pipeline. It's more a "current argument to the currently executing script block". For example while you can use it just fine in `ForEach-Object` or `Where-Object` you can't use it in something like `Get-Foo|Add-Member NoteProperty Bar ($_.SomeProperty)` – there's a pipeline involved, but no script block and therefore no `$_`. (That being said, the PowerShell help also refers to the pipeline for `$_`. Confusing.) – Joey Aug 16 '10 at 16:23
  • @Joey you can absolutely use $_ in your example. `Get-Foo | Add-Member -Type NoteProperty -Name Bar -Value $_.SomeProperty ` – Jeter-work Nov 06 '15 at 16:38
  • 3
    @Xalorous: Just because it doesn't produce an error doesn't mean it works: `Get-ChildItem | Add-Member -Type NoteProperty -Name Bar -Value $_.Name -PassThru | Select Bar` ... Well, it *can* work if you have a `$_` in the scope where you're executing that pipeline. But that's very different from what you usually mean when trying to write something like that. – Joey Nov 06 '15 at 17:47
  • @Joey `$_` in what you wrote is, for some reason, not looping through all the objects. Try this instead. `gci | % { $_ | add-member -Type NoteProperty -Name Bar -Value $_.name -PassThru } | Select Bar`. I suspect that having `gci | cmdlet` without the explicit foreach is gathering up gci results and passing an array to the cmdlet. However, the array is an object, so it's adding a property to the array object. The array does not have a 'name' property, so the value assigned to $_.Bar is $null. Bottom line is that $_ is used extensively w/ pipelining. Not needing %{} to loop through is new. – Jeter-work Nov 23 '15 at 19:18
  • Working version with extra pipeline removed. `gci | % { add-member -InputObject $_ -Type NoteProperty -Name Bar -Value $_.name -PassThru } | Select Bar` – Jeter-work Nov 23 '15 at 19:27
  • Within a PS script $_ also refers to the current directory of the execuring shell if used in the context of a path argument, for example: `Get-ChildItem -Path $_ -File` – endurium Sep 08 '22 at 09:48
48

I think the easiest way to think about this variable like input parameter in lambda expression in C#. I.e. $_ is similar to x in x => Console.WriteLine(x) anonymous function in C#. Consider following examples:

PowerShell:

1,2,3 | ForEach-Object {Write-Host $_}

Prints:

1
2
3

or

1,2,3 | Where-Object {$_ -gt 1}

Prints:

2
3

And compare this with C# syntax using LINQ:

var list = new List<int> { 1, 2, 3 };
list.ForEach( _ => Console.WriteLine( _ ));

Prints:

1
2
3

or

list.Where( _ => _ > 1)
    .ToList()
    .ForEach(s => Console.WriteLine(s));

Prints:

2
3
ilter
  • 4,030
  • 3
  • 34
  • 51
Sergey Teplyakov
  • 11,477
  • 34
  • 49
  • 7
    In C# don't use `_` as input parameter in lambda. `_` is sometimes used when the parameters is ignored, use x instead. http://stackoverflow.com/questions/424775/is-there-a-better-way-to-express-a-parameterless-lambda-than – Carlos Muñoz Oct 14 '13 at 17:54
  • I don't think Sergey meant for the reader to use that exact syntax, it was simply a demonstration of how it worked. – Mike Devenney Feb 07 '23 at 18:43
34

According to this website, it's a reference to this, mostly in loops.

$_ (dollar underscore) 'THIS' token. Typically refers to the item inside a foreach loop. Task: Print all items in a collection. Solution. ... | foreach { Write-Host $_ }

Ikke
  • 99,403
  • 23
  • 97
  • 120
12

$_ is an alias for automatic variable $PSItem (introduced in PowerShell V3.0; Usage information found here) which represents the current item from the pipe.

PowerShell (v6.0) online documentation for automatic variables is here.

Legends
  • 21,202
  • 16
  • 97
  • 123
Jeter-work
  • 782
  • 7
  • 22
4

$_ is a variable created by the system usually inside block expressions that are referenced by cmdlets that are used with pipe such as Where-Object and ForEach-Object.

But it can be used also in other types of expressions, for example with Select-Object combined with expression properties. Get-ChildItem | Select-Object @{Name="Name";Expression={$_.Name}}. In this case the $_ represents the item being piped but multiple expressions can exist.

It can also be referenced by custom parameter validation, where a script block is used to validate a value. In this case the $_ represents the parameter value as received from the invocation.

The closest analogy to c# and java is the lamda expression. If you break down powershell to basics then everything is a script block including a script file a, functions and cmdlets. You can define your own parameters but in some occasions one is created by the system for you that represents the input item to process/evaluate. In those situations the automatic variable is $_.

Alex Sarafian
  • 634
  • 6
  • 17
1

$_ is an variable which iterates over each object/element passed from the previous | (pipe).

Bill
  • 5,263
  • 6
  • 35
  • 50
0

The $_ is a $PSItem, which is essentially an object piped from another command. For example, running Get-Volume on my workstations returns Rows of PSItems, or objects

get-volume | select driveLetter,DriveType   

driveLetter DriveType
----------- ---------
      D      Fixed
             Fixed
      C      Fixed
      A      Removable

Driveletter and DriveType are properties Now, you can use these item properties when piping the output with $_.(propertyName). (Also remember % is alias for Foreach-Object) For example

$vol = get-volume | select driveLetter,DriveType

$vol | Foreach-Object {
    if($_.DriveType -eq "Fixed") {
        "$($_.driveLetter) is $($_.driveType)"}
     else{
        "$($_.driveLetter) is $($_.driveType)"
     }
 }

Using Terinary in Powershell 7, I am able to shorten the logic while using properties from the Piped PSItem

Daikyu
  • 153
  • 9