Powershell is hell

Why do you get a “Missing closing ‘)’ in expression.” error when piping a collection to a for loop in PowerShell?

This post was most recently updated on March 13th, 2023.

2 min read.

Today, I’m writing about a stupid error. Yeah, I do make those every now and then.

After adding a for loop to my PowerShell script, I started to get annoying ParserErrors about my for loop missing a closing bracket. But it was NOT missing one – what gives?

Problem

So, what I was trying to do was to concatenate a kinda random collection of strings after the first few items. I was going to iterate through the strings by piping them into a loop. After trying a for each loop I opted to use a “normal” for a loop because I didn’t want to use any extra variables and if-else blocks inside a loop to jump over the first few items.

My code was somewhat like this:

$items = Get-SomethingThatRetunsStringCollection
$items | for ($i = 3; $i -le $items.Length; $i++) { Write-Host $_ }

But that didn’t work. I got an error:

ParserError:
Line |
   1 |  $items | for ($i = 3; $i -le $items.Length; $i++) { Write-Host $_ }
     |                      ~
     | Missing closing ')' in expression.

So… How do we fix this?

Reason

This time, the reason was quite simple. You obviously can’t pipe anything to for in PowerShell. You can pipe to foreach, as it will naturally go through whatever Collection you pass to it, but for is a different beast.

For does not accept piped data, so you need to iterate through the collection another way.

Solution

Restructure your code! Let’s go through a few options:

Time needed: 6 minutes

How to make your collection iteration work in PowerShell?

  1. Iterate through the collection without piping

    Well, I suppose this one is pretty clear. Instead of piping to your for loop, you could do something like this:

    for ($i = 3; $i -le $items.Length; $i++) { Write-Host $items[$i] }

    This was my humble solution. But it wasn’t the only one I came up with :)

  2. Use a foreach -loop instead

    You can certainly use a foreach loop, too! This can be done somewhat like this:

    $skip = 3;
    $items | foreach { if ($skip -gt 0) { $skip--; } else { Write-Host $_; } }


    If the order of things isn’t important to you and the collection ($items) doesn’t contain data that would share some dependencies, you could also do a foreach -Parallel loop – it’s faster, but the order of execution is not guaranteed!

  3. Use a select with -Skip instead

    Depending on what you want to do, you could iterate through the collection by piping it to select – somewhat like below:

    $items | select -Skip 3 | foreach { Write-Host $_; }

Okay – that’s it. At the end of the day, after sporadically working with PowerShell since 2011, I can still make rookie mistakes. And I am not ashamed to share the solutions to the rookie mistakes either 😅

Anyway – these were the solutions I could quickly figure out. If you have better ones, let me know in the comments section below!

mm
5 2 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments