【问题标题】:Multiple -and -or in PowerShell Where-Object statementPowerShell Where-Object 语句中的多个 -and -or
【发布时间】: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。单击注释框旁边的帮助链接以获取格式化帮助。用反引号包围代码`

标签: powershell windows-7 windows-server-2008 windows-server-2003


【解决方案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)

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-06
    • 1970-01-01
    • 1970-01-01
    • 2012-10-15
    • 2021-02-02
    • 2017-06-11
    • 1970-01-01
    相关资源
    最近更新 更多