Эквивалент Powershell для ".Single ()" для программиста на C # / Java - PullRequest
4 голосов
/ 11 апреля 2019

Я пишу несколько сценариев для своего 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 будут указывать конкретно на эту строку и, возможно, даже включая дублирующиеся элементы.

Где-объект: значение содержит несколько элементов, где разрешен только один, доступные элементы: firstDirectory \ SomeSoftware.zip, Another-SomeSoftware.zip в C: \ Users \ geoff \ Code \ Project \ MyScript.ps1: 33 char: 73
+ ... ChildItem -Path. \ -Filter " SomeSoftware .zip" -recurse | Где -Одинокий) .Полное имя
+ ~~~~~~~
+ CategoryInfo: InvalidArgument: (:) [Get-ChildItem], SingletonSetContainsMultipleElementsException
+ FullyQualifiedErrorId: TooManyElements, Microsoft.PowerShell.Commands.WhereObjectCommand

Есть ли для меня встроенный способ сделать это? Могу ли я использовать какой-нибудь трюк PowerShell, или мне следует использовать небольшой модуль с закрытой функцией (и, если да, то какая самая элегантная реализация?)

Ответы [ 2 ]

3 голосов
/ 11 апреля 2019

Вы всегда можете просто использовать 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 голос
/ 11 апреля 2019

Если вы хотите 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, еслиВы хотели бы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...