Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple -and -or in PowerShell Where-Object statement

PS H:\> Invoke-Command -computername SERVERNAME { Get-ChildItem -path E:\dfsroots\datastore2\public} | Where-Object {{ $_.e
xtension-match "xls" -or $_.extension-match "xlk" } -and  { $_.creationtime -ge "06/01/2014"}}

Above is my code example. I'm trying to remotely run this PowerShell code on my file server and have it return all .xls and .xlk files with a creation date on or later than 6/1/2014. When I run this code it starts spitting out all of the folders in that remote location. If I only compare two things like so:

PS H:\> Invoke-Command -computername SERVERNAME { Get-ChildItem -path E:\dfsroots\datastore2\public} | Where-Object { $_.extension-match "xls" -and  $_.creationtime -ge "06/01/2014"}

Only the xls files created on or after that date display. What's going on here? Do I need to use something other than nest -and and -or statements?

like image 594
Winski Tech Avatar asked Jul 10 '14 17:07

Winski Tech


2 Answers

By wrapping your comparisons in {} in your first example you are creating ScriptBlocks; so the PowerShell interpreter views it as Where-Object { <ScriptBlock> -and <ScriptBlock> }. Since the -and operator operates on boolean values, PowerShell casts the ScriptBlocks to boolean values. In PowerShell anything that is not empty, zero or null is true. The statement then looks like Where-Object { $true -and $true } which is always true.

Instead of using {}, use parentheses ().

Also you want to use -eq instead of -match since match uses regex and will be true if the pattern is found anywhere in the string (try: 'xlsx' -match 'xls').

Invoke-Command -computername SERVERNAME { 
    Get-ChildItem -path E:\dfsroots\datastore2\public | 
        Where-Object {($_.extension -eq ".xls" -or $_.extension -eq ".xlk") -and ($_.creationtime -ge "06/01/2014")}
}

A better option is to filter the extensions at the Get-ChildItem command.

Invoke-Command -computername SERVERNAME { 
    Get-ChildItem -path E:\dfsroots\datastore2\public\* -Include *.xls, *.xlk | 
        Where-Object {$_.creationtime -ge "06/01/2014"}
}
like image 84
Rynant Avatar answered Nov 19 '22 06:11

Rynant


You're using curvy-braces when you should be using parentheses.

A where statement is kept inside a scriptblock, which is defined using curvy baces { }. To isolate/wrap you tests, you should use parentheses ().

I would also suggest trying to do the filtering on the remote computer. Try:

Invoke-Command -computername SERVERNAME {
    Get-ChildItem -path E:\dfsroots\datastore2\public |
    Where-Object { ($_.extension -eq "xls" -or $_.extension -eq "xlk") -and $_.creationtime -ge "06/01/2014" }
}
like image 8
Frode F. Avatar answered Nov 19 '22 05:11

Frode F.