Исключения и трубопроводы Powershell Get-ChildItem

Я работаю над сценарием Powershell для сравнения каталогов и хочу по возможности очистить часть кода. Сценарий в целом работает точно так, как я хочу, но я чувствую, что код, который я включил ниже (который является лишь небольшой частью), мог бы быть написан лучше.

Для приведенного ниже кода основное внимание уделяется получению исключений из CSV-файла и включению их в Get-ChildItem. Я обнаружил, что вы не можете извлекать исключенные пути из csv так же, как и файлы (поскольку пути имеют дело с FullName vs Name, а также с подстановочными знаками для включенных папок и серверов).

Так что то, что я имею ниже, работает для меня. Но есть ли способ сделать часть Where-Object, которая занимается исключением путей в функцию, так как мне приходится вызывать ее дважды? Я пытался просто превратить это в функцию и добавить в конец, но это не работает. Я также попытался поместить это в начале как функцию, но это тоже не сработало. И я знаю, что когда вы имеете дело с функциями и данными конвейера, вы должны настроить их особым образом. Так что, возможно, я просто делаю что-то не так. В любом случае, если у вас есть предложение, как это убрать или сделать его более эффективным, я открыт для просмотра того, что у вас есть.

$ExcludedPaths = @(Import-Csv -LiteralPath 'D:\ExclusionList.csv') |Select-Object -Expand ExcludedPaths
$ExcludedFiles = @(Import-Csv -LiteralPath 'D:\ExclusionList.csv') |Select-Object -Expand ExcludedFiles

$SourceFiles = Get-ChildItem -Recurse -Path $SourceDir -Exclude $ExcludedFiles -Force | Where-Object {
    $FullName = $_.FullName
    -not($ExcludedPaths|Where-Object {
        $FullName -like "$_*"
    })
}
$DestFiles = Get-ChildItem -Recurse -Path $DestDir -Exclude $ExcludedFiles -Force | Where-Object {
    $FullName = $_.FullName
    -not($ExcludedPaths|Where-Object {
        $FullName -like "$_*"
    })
}

1 ответ

Решение

Абстрагировать логику в вашем скрипте в отдельную функцию довольно просто.

Мы начнем с определения переменных частей подпрограммы - это будут наши параметры. В вашем случае это -Path а также -Exclude параметры переданы Get-ChildItem и $ExcludePaths массив для внутреннего Where-Object,

Повторно используя те же имена параметров, что и целевой командлет (Get-ChildItem), мы можем легко $PSBoundParameters переменная, поэтому нам не нужно вручную проверять, является ли -Exclude аргумент был пройден или нет. Аналогично с $ExcludePathsдополнительная проверка не требуется, так как подача заявки -not в пустой массив всегда вернется $true,

Таким образом, мы получаем что-то вроде:

function Get-ChildItemFiltered
{
    param(
        [Parameter(Mandatory)]
        [string[]]$Path,
        [string[]]$Exclude,
        [string[]]$ExcludePaths
    )

    if($PSBoundParameters.ContainsKey('ExcludePaths')){
        $PSBoundParameters.Remove('ExcludePaths')
    }

    Get-ChildItem -Recurse -Force @PSBoundParameters | Where-Object {
        $FullName = $_.FullName
        -not($ExcludePaths|Where-Object {
            $FullName -like "$_*"
        })
    }
}

И ваш сценарий оказывается намного проще:

$SourceFiles = Get-ChildItem -Path $SourceDir -Exclude $ExcludedFiles -ExcludePaths $ExcludedPaths
$DestFiles   = Get-ChildItem -Path $DestDir -Exclude $ExcludedFiles -ExcludePaths $ExcludedPaths

Кроме того, вы можете сохранить фильтр, который вы используете для Where-Object в блоке скриптов:

$ExcludedPaths = @(Import-Csv -LiteralPath 'D:\ExclusionList.csv') |Select-Object -Expand ExcludedPaths
$ExcludedFiles = @(Import-Csv -LiteralPath 'D:\ExclusionList.csv') |Select-Object -Expand ExcludedFiles

$Filter = {
    $FullName = $_.FullName
    -not($ExcludedPaths|Where-Object {
        $FullName -like "$_*"
    })
}

$SourceFiles = Get-ChildItem -Recurse -Path $SourceDir -Exclude $ExcludedFiles -Force | Where-Object -FilterScript $Filter
$DestFiles = Get-ChildItem -Recurse -Path $DestDir -Exclude $ExcludedFiles -Force | Where-Object -FilterScript $Filter
Другие вопросы по тегам