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

Solution 1:

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.