【问题标题】:Powershell Get-ChildItem exclusions and pipingPowershell Get-ChildItem 排除和管道
【发布时间】:2018-03-26 14:27:28
【问题描述】:

我正在编写一个 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 "$_*"
    })
}

【问题讨论】:

    标签: powershell pipeline get-childitem exclusionpath


    【解决方案1】:

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

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

    通过重用与目标 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
    

    【讨论】:

    • 谢谢!我选择了第二个选项,因为它更紧凑(坦率地说,我更了解它,因为我对 PS 很陌生)。效果很好!
    • @JeremiahWilliams 很高兴它为您工作!不过,我建议将函数示例作为学习练习。 PowerShell 很有趣! :-D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-22
    • 2016-12-19
    相关资源
    最近更新 更多