PowerShell Where-Object语句中的多个-and-或操作

57
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"}}
以上是我的代码示例。我正在尝试远程运行此PowerShell代码并使其返回创建日期在2014年6月1日或之后的所有.xls和.xlk文件。运行此代码时,它开始输出该远程位置中的所有文件夹。如果我只比较两个东西,如下所示:
PS H:\> Invoke-Command -computername SERVERNAME { Get-ChildItem -path E:\dfsroots\datastore2\public} | Where-Object { $_.extension-match "xls" -and  $_.creationtime -ge "06/01/2014"}

只有在那个日期之后创建的 xls 文件才会显示。这是怎么回事?我需要使用除了嵌套 -and-or 语句之外的其他内容吗?


请注意,将命令分解为多个“where”语句也不起作用。我输入的命令如下:PS H:> Invoke-Command -computername SERVERNAME { Get-ChildItem -path E:\dfsroots\datastore2\public} | Where-Object { $.extension-match "xls" -or $.extension-match "xlk" } | where-object { $_.creationtime -ge "06/01/2014"}然后它开始输出xlsx文件,这不是我想要的。 - Winski Tech
3
使用括号而不是花括号来包含选项,因此 Where{($_.Extension -Match "xls" -or $_.Extension -Match "xlk") -and $_.CreationTime -ge "06/01/2014"} - TheMadTechnician
@TheMadTechnician,能帮我一下吗?我无法弄清楚哪些迷你Markdown格式有效,哪些无效。你是如何将那个内容包含在“代码”块中的? - Winski Tech
@TheMadTechnician 即使使用括号,结果仍然会输出xlsx文件。 - Winski Tech
@WinskiTech 关于 Markdown。单击评论框旁边的帮助链接以获取格式化帮助。使用反引号 ``` 包围代码。 - Rynant
那么不要使用-Match,而应该使用-eq。 - TheMadTechnician
3个回答

69

在您的第一个示例中,通过将比较语句包装在 {} 中,您创建了脚本块。因此,PowerShell 解释器将其视为 Where-Object { <ScriptBlock> -and <ScriptBlock> }。由于 -and 运算符对布尔值进行操作,PowerShell 将 ScriptBlocks 强制转换为布尔值。在 PowerShell 中,未空、0 或 null 的任何内容都是 true。语句看起来像 Where-Object { $true -and $true },这总是成立。

请改用括号 (),而不是使用 {}

此外,您需要使用 -eq 而不是 -match,因为 match 使用正则表达式,如果在字符串中找到匹配的模式,则为 true(试一下:'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")}
}

更好的选择是在Get-ChildItem命令中过滤扩展名。

Invoke-Command -computername SERVERNAME { 
    Get-ChildItem -path E:\dfsroots\datastore2\public\* -Include *.xls, *.xlk | 
        Where-Object {$_.creationtime -ge "06/01/2014"}
}

括号没有解决问题,只是改变了输出结果,我想要搜索的是xls和xlk文件,但却得到了xlsx文件。 - Winski Tech
请看我的编辑。-match 运算符将在字符串的任何位置进行匹配。 - Rynant

10

当你应该使用括号时,你正在使用花括号。

where语句位于脚本块内,该脚本块使用花括号{ }定义。为了隔离/包装测试,应使用括号()

我还建议尝试在远程计算机上进行过滤。请尝试:

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" }
}

括号并没有解决问题,只是改变了输出结果,当我试图搜索xls和xlk文件时,我仍然得到xlsx文件。 - Winski Tech
1
你也使用了错误的运算符。很抱歉没有发现这个问题。你需要使用“-eq”来获取精确匹配。“-match”会包括所有包含短语“xls”的扩展名结果。 :) - Frode F.

1

我在这里找到了解决方案:

如何在PowerShell复制脚本中正确过滤多个字符串

你必须使用-Include标志来使用 Get-ChildItem

我的示例:

$Location = "C:\user\files" 
$result = (Get-ChildItem $Location\* -Include *.png, *.gif, *.jpg)

不要忘记在路径位置后加上“*”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接