Исключения и трубопроводы 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