Powershell Get-ChildItem 排除项和管道

Powershell Get-ChildItem exclusions and piping

我正在编写一个 Powershell 脚本来比较目录,如果可能的话,我想清理一些代码。整个脚本的工作方式与我想要的完全一样,但我觉得我在下面包含的代码(这只是其中的一小部分)可以写得更好。

对于下面的代码,它着重于从 csv 文件中获取排除项并将它们合并到 Get-ChildItem 中。我发现您不能像从文件中提取排除的路径那样从 csv 中提取排除的路径(因为路径处理 FullName 与 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 "$_*"
    })
}

将脚本中的逻辑抽象为一个单独的函数非常简单。

我们首先确定例程的可变部分 - 这些将是我们的参数。在您的情况下,这是传递给 Get-ChildItem-Path-Exclude 参数以及内部 Where-Object.

$ExcludePaths 数组

通过重复使用与目标 cmdlet (Get-ChildItem) 相同的参数名称,我们可以轻松地拼写 $PSBoundParameters 变量,因此我们不必手动检查 -Exclude 参数是否通过。与 $ExcludePaths 类似,不需要额外的检查,因为将 -not 应用于空数组将始终 return $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