我正在为CI编写一些脚本,并且我注意到我在声明过滤器的唯一性方面做得不好。例如,一个脚本假定
$availableZip = $(Get-ChildItem -Path .\ -Filter "*SomeName*.zip" -Recurse).FullName
将提供一个唯一的条目,但可能不提供任何条目,也可能提供多个条目。
这当然可以通过一些If-Else检查在下游进行处理,但是我想做的就是优雅地将PowerShell推送给我,从而产生错误,例如
$availableZip = $(Get-ChildItem -Path .\ -Filter "*SomeName*.zip" -Recurse | Where -Single).FullName
使得Where -Single
会抛出某种SetIsEmptyException
或SetContainsMultipleElementsException
,而所有PowerShell附件都专门指向此行,甚至可能包括重复的成员。
Where-Object:值包含多个元素,其中仅允许一个元素, 可用元素:firstDirectory \ SomeSoftware.zip,Other-SomeSoftware.zip 在C:\ Users \ geoff \ Code \ Project \ MyScript.ps1:33 char:73
+ ... ChildItem -Path。\ -Filter“ SomeSoftware .zip” -recurse |其中-Single).FullName
+ ~~~~~~~~
+ CategoryInfo:InvalidArgument:(:) [Get-ChildItem],SingletonSetContainsMultipleElementsException
+ FullyQualifiedErrorId:TooManyElements,Microsoft.PowerShell.Commands.WhereObjectCommand
我是否有内置的方法来执行此操作?有什么可以使用的PowerShell技巧,还是应该使用带有私有功能的小模块(如果可以的话,最优雅的实现是什么?)
答案 0 :(得分:3)
您总是可以像下面那样使用Linq。我试图通过首先只获取zip文件夹的名称来使其更加高效。
[string[]]$zips = @(Get-ChildItem -Path .\ -Filter "*SomeName*.zip" -Recurse -Name)
[string]$availableZipName = [System.Linq.Enumerable]::Single($zips)
$availableZip = Get-ChildItem -Path $availableZipName -Recurse
下面,我将其放入函数中以便于使用。
function Get-AvailableZip (
[ValidateScript({ Test-Path $_ })]
[string]$Path,
[ValidateNotNullOrEmpty()]
[string]$Filter
)
{
[string[]]$zips = @(Get-ChildItem -Path $Path -Filter $Filter -Recurse -Name);
[string]$availableZipName
$availableZip = $null
try
{
$availableZipName = [System.Linq.Enumerable]::Single($zips)
$availableZip = Get-ChildItem -Path "$Path\$availableZipName" -Recurse
}
catch [System.InvalidOperationException]
{
if ($_.Exception.Message -eq "Sequence contains more than one element")
{
Write-Error -Message ([Environment]::NewLine + $_.Exception.Message + [Environment]::NewLine + "Files Found:" + [Environment]::NewLine + [string]::Join([Environment]::NewLine, $zips)) -Category LimitsExceeded -Exception ($_.Exception)
}
else
{
if ($_.Exception.Message -eq "Sequence contains no elements")
{
Write-Error -Message ([Environment]::NewLine + $_.Exception.Message) -Category ObjectNotFound -Exception ($_.Exception)
}
else
{
throw
}
}
}
return $availableZip;
}
用法:
Get-AvailableZip -Path ".\" -Filter "*SomeName*.zip"
答案 1 :(得分:1)
如果您要A.使用管道,则B.具有可重复使用的功能,而C.具有相当快的功能:
function Where-SingleObject {
param (
[Parameter(Mandatory, ValueFromPipeline, HelpMessage='Data to process')]$InputObject
)
begin {
$i = 0
}
process {
if($i -eq 1) {
throw "Error"
}; $i++
}
end {
return $InputObject
}
}
(Get-ChildItem -Path '' -Filter '' -Recurse).FullName | Where-SingleObject
如果愿意,您可以删除Mandatory
并为0添加自定义错误。