1

我正在使用 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 "$_*"
    })
}
4

1 回答 1

0

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

我们首先确定例程的可变部分——这些将是我们的参数。在您的情况下,这是传递给的-Pathand参数和 inner的数组。-ExcludeGet-ChildItem$ExcludePathsWhere-Object

通过重用与目标 cmdlet ( ) 相同的参数名称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
于 2018-03-26T14:53:44.057 回答