如何将Where-Object简写运算符应用于整个PowerShell对象?
已知的简写用法
我们知道PowerShell的Where-Object支持简写语法,不用写脚本块就能直接对属性应用运算符,比如把:
Get-ChildItem | Where-Object { $_.Name -match '\.(txt|md)$' }
简化成:
Get-ChildItem | Where-Object Name -match '\.(txt|md)$'
需求与问题
现在想实现直接对整个输入对象应用运算符的简写,替代下面这条先提取属性再过滤的命令:
Get-ChildItem | ForEach-Object Name | Where-Object { $_ -match '\.(txt|md)$' }
但直接写Where-Object -match '\.(txt|md)$'会报错:
Where-Object: The specified operator requires both the -Property and -Value parameters. Provide values for both parameters, and then try the command again.
尝试用*或_等特殊字符作为属性名也无效,查文档发现-Match对应的-Property参数是必填项。
解决方案
最直接的替代写法(效果一致)
其实不需要先提取Name属性再过滤,直接对Get-ChildItem返回的FileInfo/DirectoryInfo对象使用-match即可——PowerShell会自动调用对象的ToString()方法,而这类对象的ToString()默认返回文件名。写法如下:Get-ChildItem | Where-Object { $_ -match '\.(txt|md)$' }这条命令和你原本的需求效果完全相同。
关于简写语法的限制
遗憾的是,Where-Object的运算符简写语法(直接用-match这类运算符作为参数的形式)必须指定具体属性名,设计上就不支持直接针对整个输入对象使用。所以不存在完全符合你预期的“简写形式”,只能用脚本块写法实现需求。
报错原因解释
报错提示里的-Value确实容易误导,它实际就是指后面的正则表达式,但核心问题是:这种简写语法要求必须先指定要操作的属性(位置上第一个参数),再提供运算符和匹配值,缺少属性名参数就会触发错误。
内容的提问来源于stack exchange,提问作者Dominik Kaszewski

