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
我正在编写一个 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