PowerShell and the hidden art of curly braces and other braces

Well, today is a very interesting day: a customer has reported an issue with a product I’m responsible for. Unfortunately, every experienced person in the customer’s company is on holiday, so a rookie has contacted me about this issue. While I’ve managed to get enough information from the log files, now I need some more traces run. I’ve sent the guy an instrumented version of the product and now I’m waiting for a reply. And I’m waiting …. God, you can tell there’s a rookie on the other end of the line: he didn’t say he received the patch and he’s not answering his phone.
And I have another project in stabilization phase requiring all my attention; try to focus on stabilizing some source code while knowing another, higher priority, request can arrive …
So what can I do to use the time? Well, learn something, that’s for sure.
Here we go: a few days ago I’ve found out how to rename a batch of files based on a pattern (change spaces to underscores, to be more specific). I was puzzled at the moment about the curly brackets syntax, so it seems now is a good time to solve this puzzle.

The curly brackets are to be used for what the PowerShell manual names “block expressions”.
For example:

Get-Service | where { $_.status -eq "stopped" }

A C# developer should see the block expression as a lambda.
The following C# block is equivalent:

var servicesList = GetServices();
var stoppedServicesList = servicesList.Where( i => i.status == "stopped" );
// Process the list - you can write it to the console, for example.

And now I can come closer to understanding the following PowerShell command:

gci | Rename-Item - NewName { $_.name -replace " ", "_" }

The equivalent C# (pseudo)code would be:

var worker = new DirectoryInfo( Directory.GetCurrentInfo() );
var filesList = DirectoryInfo.GetFiles();
foreach( var file in filesList )
{
    var newName = ( i => i.Replace( " ", "") ) (file.Name );
    File.Move( file.Name, newName );
}

There’s one item I have to clarify: the -replace parameter (or, better, operator). That’s how PowerShell allows variables manipulations with less typing.
Type the following commands at a PowerShell console:

$a="This file name has spaces and this breaks some scripting shells"
$b=$a -replace " ", ""

You will see the $b variable contains the initial file name without the spaces. It’s a powerful feature of PowerShell.