PowerShell–The “unexpected token ‘and’” error message explained

Lots of people that are used scripting languages, such as VBS or Kix, and start using PowerShell contact me about the infamous “Unexpected token ‘and’” error message.
I found this to be funny because I ran into that one myself in my early PowerShell days Smile
So, lets go back in time to the point where I was just started using PowerShell and was playing around with it…

When creating a PowerShell script to find a file based on some criteria, my way of thinking would provide something like this:

$MSI = get-childitem $TargetPath –recurse | where ({$_.Extension -match “msi”} and {$_.Name -match “LiveMessenger”})

But… it will give an error stating that there is an “unexpected token ‘and'”… very annoying.
Since I was used to scripting in VBS, Batch and Kix I thought this was very strange, the syntax should have worked, right? Wrong…
PowerShell is an object based scripting language so a little bit of thinking needs to be changed, compared to what I would like to call ‘VBS thinking’.

With PowerShell it is possible to use the output of a first command as the input of the command that comes after it by using a technique called ‘piping’.
So, instead of using an ‘and’ statement, we could simply use the output of the first filter command as the input of the second filter command.
With this in mind, a change can be made. The following command uses the piping technique instead of an ‘and’ statement… and will work without that nasty “unexpected token ‘and'” error. Why? Simply because the ‘and’ statement is not being used anymore.

$MSI = get-childitem $TargetPath –recurse | where {$_.Extension -match “msi”} | where {$_.Name -match “LiveMessenger”}

And by using the piping technique, you can simply go even further and, if you would like that, you can filter even further!
Next to not getting an error, the piping technique is very CPU friendly compared to the ‘and’ statement.
The ‘and’ statement would cause the entire criteria to be tested on every single object, where the piping technique filters down the objects at every step which causes the list of objects for the second filter to be smaller… and so on. Far more elegant, right?

So, what does this all mean?
If you’re used to scripting languages like VBS or Kix, PowerShell will require a little change in your thinking. Don’t think about AND statements… instead, think about piping such as shown above Smile

 

2 comments

  1. David says:

    Hi,
    I would not recommend to use two pipelines in a row. You can use AND there, but in PowerShell you need to have it in a slightly different way (even I don’t know what you mean with property ‘Authors’):

    $MSI = get-childitem $TargetPath –recurse | where { $_.Extension -match “msi” -and $_.Authors -match “Microsoft” } 

    a bit better way is this:
    $MSI = get-childitem $TargetPath –recurse -include *.msi | where { $_.Authors -match “Microsoft”}

    David

  2. Jeff Wouters says:

    Hi David,
    Thanks for your feedback, regarding the “Authors” property you are totally correct… it doesn’t exsist. That’s what I get when trying to script several scripts at the same time 🙁

    Regarding your statement not to recommend to use two pipelines in a row I have to disagree, but perhaps that’s just a personal thing.
    I always like to build a big command out of several smaller commands, which allows non-scripters to get a quick overview and understand what the script does… yes, comments in scripts are a must but still…
    But in this case you last command would indeed be a better approach since the first filtering can be done in the first block 🙂

    Jeff.

Leave a Reply

Your email address will not be published. Required fields are marked *