Powershell – Why does ForEach behave differently than % even though they are both aliases of ForEach-Object in Powershell

powershell

For some reason the % alias for ForEach-Object throws an exception when using the ( $Thing in $Things) syntax while the ForEach alias works fine.

Here are two examples:

Using the % alias:

$ints = @(1, 2, 3, 4, 5)
% ($i in $ints)
{Write-Host $i}

This fails with the error Unexpected token 'in' in expression or statment.

Using the ForEach alias:

$ints = @(1, 2, 3, 4, 5)
foreach ($i in $ints)
{Write-Host $i}

This succeeds without issue.

Why is there a difference if they are both aliases of ForEach-Object?

Best Answer

These are two different things:

% is the alias for the cmdlet ForEach-Object and foreach is also the alias for the cmdlet ForEach-Object... and foreach is a looping statement which does not work with pipelining.

As written, your first command expands to:

ForEach-Object ($i in $ints) {
  Write-Host $i 
}

...which isn't valid syntax for the ForEach-Object cmdlet.

When foreach appears, as with your second command, it is interpreted as a foreach statement, not the cmdlet alias. In this case the syntax is valid and loops as expected.

You can compare the differences with get-help about_Foreach and get-help ForEach-Object. This blog post Essential PowerShell: Understanding foreach also does a nice job explaining.