PowerShell Where-Object 语句中的多个 -and -or

Posted

技术标签:

【中文标题】PowerShell Where-Object 语句中的多个 -and -or【英文标题】:Multiple -and -or in PowerShell Where-Object statement 【发布时间】:2014-09-01 04:56:37 【问题描述】:
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" - 或 $_.extension-match "xlk" | where-object $_.creationtime -ge "06/01/2014" 它开始吐出 xlsx 文件,这不是我想要的。 使用圆括号而不是大括号来包围选项,所以Where($_.Extension -Match "xls" -or $_.Extension -Match "xlk") -and $_.CreationTime -ge "06/01/2014" @TheMadTechnician 如果你能帮我一分钟,我不知道什么 mini-Markdown 格式有效,什么无效。您是如何将其包含在“代码”块中的? @TheMadTechnician 即使使用括号,结果仍然会输出 xlsx 文件。 @WinskiTech 回复:Markdown。单击注释框旁边的帮助链接以获取格式化帮助。用反引号包围代码` 【参考方案1】:

通过在您的第一个示例中将您的比较包装在 中,您正在创建脚本块;因此 PowerShell 解释器将其视为Where-Object <ScriptBlock> -and <ScriptBlock> 。由于 -and 运算符对布尔值进行操作,因此 PowerShell 将 ScriptBlocks 转换为布尔值。在 PowerShell 中,任何非空、零或 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 文件。 查看我的编辑。 -match 运算符将匹配字符串中的任何位置。【参考方案2】:

当你应该使用括号时,你使用了大括号。

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 文件。 您还使用了错误的运算符。很抱歉没有抓住那个。您需要使用 -eq 来获得完全匹配。 -match 将包括所有扩展名包含短语“xls”的结果。 :)【参考方案3】:

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

How to properly -filter multiple strings in a PowerShell copy script

Get-ChildItem 必须使用 -Include 标志

我的例子:

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

别忘了在路径位置后加上“*”。

【讨论】:

以上是关于PowerShell Where-Object 语句中的多个 -and -or的主要内容,如果未能解决你的问题,请参考以下文章

如何像 IN 语句一样使用 Powershell Where-Object

PowerShell Where-Object 语句中的多个 -and -or

PowerShell Where-Object 筛选出包含指定内容的行

powershell 关于如何实现同一属性上的多个条件的简化Where-Object的概念证明

Where-Object 多个条件不起作用

powershell PowerShell配置文件问候语