2

In this answer the author proposed the following snippet:

dir -Path C:\FolderName -Filter *.fileExtension -Recurse | %{$_.FullName}

I can understand the majority of it, but I'm unable to search documentation for the last part. The output of the search is piped | and used in %{} and as $_.

I have experimented around it, %{} is a for-each statement I believe, bing search was not effective. $_ is also somewhat magic: it is a variable, with no name and thus immediately consumed? I don't care much for the .FullName, that part I sorted out. Again, bing search was not effective, nor searching for those char sequences in PowerShell docs.

Can anybody explain it to me?

2
  • 1
    It represents the object(s) passed down the pipeline. That's why you were able to reference the property of .Fullname. Commented Mar 10, 2021 at 14:46
  • Just like you would store an object in a variable, such as : $Var = Get-Process -Name wuasrv in this case, I can reference the objects properties using dot notation: $Var.Name, $_ is the same concept. It's a place holder for the actual object passed down. Commented Mar 10, 2021 at 14:53

2 Answers 2

6

%{} is not "a thing" - it's two things: % and {}

% is an alias for the ForEach-Object cmdlet:

PS ~> Get-Alias '%'
CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Alias           % -> ForEach-Object

... so it resolves to:

... |ForEach-Object { $_.FullName }

ForEach-Object is basically PowerShell's map function - it takes input via the pipeline and applies the operation described in the {} block to each one of them.

$_ is an automatic reference to the current pipeline input item being processed

You can think of it a bit like a foreach($thing in $collection){} loop:

1..10 |ForEach-Object { $_ * 10 }
# produces the same output as
foreach($n in 1..10){
    $n * 10
}

Except we can now stick our loop in the middle of a pipeline and have it produce output for immediate consumption:

1..10 |ForEach-Object { $_ * 10 } |Do-SomethingElse

ForEach-Object is not the only thing that makes use of the $_ automatic variable in PowerShell - it's also used for pipeline-binding expressions:

mkdir NewDirectory |cd -Path { $_.FullName }

... as well as property expressions, a type of dynamic property definition supported by a number of cmdlets like Sort-Object:

1..10 |Sort-Object { -$_ } # sort in descending order without specifying -Descending

... Group-Object:

1..10 |Group-Object { $_ % 3 } # group terms by modulo congruence

... and Select-Object:

1..10 |Select-Object @{Name='TimesTen';Expression={$_ * 10}} # Create synthetic properties based on dynamic value calculation over input 
Sign up to request clarification or add additional context in comments.

1 Comment

One nice thing about Visual Studio Code is if you install the powershell addin it will warn you about using alias and tell you what the alias refers to.
3

To complement Mathias' answer, which explains the specific constructs well, with how you could / couldn't have discovered this information yourself, using PowerShell's own help system:

Relevant help topics and use of the help system:

Note: To get an overview of all aspects of PowerShell's help system, simply run help.

  • % is a built-in alias for the ForEach-Object cmdlet:

    • Use Get-Help ForEach-Object to view the help topic in the terminal.
      • If no local topics are found, you must download them via the Update-Help cmdlet.
    • Tips:
      • Add the -Online switch to open the (potentially more current) online version of the topic in your browser.

      • You can bootstrap your use of Get-Help with Get-Help Get-Help (or even help help):

        • Cmdlet-specific help comes in detail levels: terse (default, shows the syntax and overview description only), -Detailed (includes parameter descriptions and example commands) and -Full (additionally includes technical parameter information and extended notes).
        • -Examples can be used to show example commands only.
        • With keyword-based search (see below), you can limit results to topics of a certain category with the -Category parameter.
      • For convenience, you can also use the built-in help function, which wraps Get-Help calls with display paging (simply put: by piping the output to the more utility) and defaults to detail level -Full.

  • {...} is a script block literal, a block of arbitrary PowerShell code that can be invoked on demand:

    • help about_Script_Blocks shows the topic locally; the about_ prefix indicates that the topic is a conceptual help topic (rather than one covering a specific command); when you use Get-Help to search for a keyword (see below), you can (somewhat obscurely) limit the results to conceptual topics with -Category HelpFile.
    • Note: As of this writing, about_ topics can not yet be directly viewed online by adding -Online - see GitHub issue #13550 - but it's easy to google them by name.
  • $_ is a variable, as the $ sigil followed by an identifier implies, and is more specifically an automatic (built-in) variable:

    • help about_Variables covers variables in general.
    • help about_Automatic_Variables covers the automatic ones.

How the above can / cannot be discovered based on symbols and aliases alone:

Doing a web search for symbols is notoriously unhelpful.

  • As an aside: Running distinct syntax constructs such as % and { ... } together without whitespace between them (e.g. %{$_.FullName}) constitutes an additional barrier, and should therefore be avoided.

Narrowing your search by using only PowerShell's help system helps, but only to a limited degree:

  • %

    • Because Get-Help is aware of aliases, help % actually works fine and directly shows ForEach-Object's help topic.
    • help % -Examples shows example commands that include the use of script blocks and the automatic $_ variable.
  • Even though Get-Help supports keyword-based search, searching for symbol-based terms {} and $_ directly isn't helpful, because even when limiting the search to conceptual (about_-prefixed topics) with -Category HelpFile, there are either too many hits (help '$_' -Category HelpFile) or the relevant topic doesn't show at all (help '{}' -Category HelpFile)

  • $_ can be discovered indirectly, IF you already know that it is an instance of a variable:

    • help variables -Category HelpFile happens to take you directly to the relevant (local) about_Automatic_Variables topic,
    • whereas help variable -Category HelpFile lists the following matching topics about_Variable_Provider, ``, about_Automatic_Variables, about_Preference_Variables, about_Remote_Variables, about_Variables, and about_Environment_Variables
    • Note: Thanks to PowerShell's pervasive support for wildcard expressions, you could have performed the search also as follows: help about*variable* - be sure to enclose both sides of the search term in *.
  • {...} can be discovered indirectly, IF you already know that it is an instance of a script (code) block:


Potential future improvements:

  • It would be a great improvement if PowerShell's help system supported focused symbol-based searches.

  • Similarly, the ability to directly look up operators, such as -match, the regular-expression matching operator, would be helpful:

    • GitHub issue #11339 proposes just that.

    • On a related note, GitHub issue #11338 proposes adding the ability to look up documentation for .NET types (online).

    • This answer contains custom functions Show-OperatorHelp and Show-TypeHelp, which fill that gap for now (also available as Gists).

3 Comments

I'd give +2 on this one. Websearch (especially on MS systems...) could help a little more. I didn't know about the help function, PowerShell is still pretty new to me.
Glad to hear it, @DaemonPainter. PowerShell is pretty "self-aware" in general - other helpful commands are Get-Command and Get-Member - but the help system certainly has room for improvement. Note that PowerShell (Core) 7+ now provides a bootstrapping hint when you enter an interactive shell: Type 'help' to get help. Running help shows a high-level overview of PowerShell's help system.
Nice extra documentation. Some concepts are clearer for me now !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.