如何直接通过管道传输到 Copy-Item 而不是在 ForEach-Object 中
How to pipe directly to Copy-Item instead of within a ForEach-Object
因为 Get-ChildItem 的 -Exclude 参数在使用 -Recurse 标志时不过滤子文件夹,请参阅 unable-to-exclude-directory-using-get-childitem-exclude-输入参数
powershell
但是 -Exclude 参数可用于过滤掉根级别的文件夹
我写了自己的递归函数:
function Get-ChildItem-Recurse() {
[cmdletbinding()]
Param(
[parameter(ValueFromPipelineByPropertyName = $true)]
[alias('FullName')]
[string[]] $Path,
[string] $Filter,
[string[]] $Exclude,
[string[]] $Include,
[switch] $Recurse = $true,
[switch] $File = $false
)
Process {
ForEach ( $P in $Path ) {
Get-ChildItem -Path $P -Filter $Filter -Include $Include -Exclude $Exclude | ForEach-Object {
if ( -not ( $File -and $_.PSIsContainer ) ) {
$_
}
if ( $Recurse -and $_.PSIsContainer ) {
$_ | Get-ChildItem-Recurse -Filter $Filter -Exclude $Exclude -Include $Include -Recurse:$Recurse
}
}
}
}
}
当我将结果通过管道传递给 ForEach-Object 以将结果复制到不同的目的地时,一切正常,除了与排除参数匹配的项目外,其他项目都被复制
$source = 'D:\Temp\'
$destination = 'D:\Temp_Copy\'
Get-ChildItem-Recurse -Path $source -Exclude @( '*NotThis*', '*NotThat*' ) | ForEach-Object {
$_ | Copy-Item -Destination ( "$($destination)$($_.FullName.Substring($source.Length))" ) -Force
}
当我将其直接通过管道传输到 Copy-Item commandlet 时,出现空值错误,因为 .Substring() 是在显然为 null
的 $_.FullName 上调用的
Get-ChildItem-Recurse -Path $source -Exclude @( '*NotThis*', '*NotThat*' ) |
Copy-Item -Destination ( "$($destination)$($_.FullName.Substring($source.Length))" ) -Force
因为本机命令行开关 Get-ChildItem 确实允许我将其结果通过管道传递给 Copy-Item,我喜欢我自己的自定义函数也能够做到这一点。但是我不明白为什么它不起作用。
使用脚本块将管道输入值动态绑定到参数:
Get-ChildItem ... |Copy-Item -Destination { "$($destination)$($_.FullName.Substring($source.Length))" }
mklement0 的以下回答详细介绍了这种动态绑定(追溯命名为 "delay-bind scriptblocks",或通俗地称为“管道绑定脚本块”):
通常您通过管道将源复制:
$source = 'D:\Temp\'
$destination = 'D:\Temp_Copy\'
get-childitem $source | copy-item -destination $destination -whatif
因为 Get-ChildItem 的 -Exclude 参数在使用 -Recurse 标志时不过滤子文件夹,请参阅 unable-to-exclude-directory-using-get-childitem-exclude-输入参数 powershell
但是 -Exclude 参数可用于过滤掉根级别的文件夹
我写了自己的递归函数:
function Get-ChildItem-Recurse() {
[cmdletbinding()]
Param(
[parameter(ValueFromPipelineByPropertyName = $true)]
[alias('FullName')]
[string[]] $Path,
[string] $Filter,
[string[]] $Exclude,
[string[]] $Include,
[switch] $Recurse = $true,
[switch] $File = $false
)
Process {
ForEach ( $P in $Path ) {
Get-ChildItem -Path $P -Filter $Filter -Include $Include -Exclude $Exclude | ForEach-Object {
if ( -not ( $File -and $_.PSIsContainer ) ) {
$_
}
if ( $Recurse -and $_.PSIsContainer ) {
$_ | Get-ChildItem-Recurse -Filter $Filter -Exclude $Exclude -Include $Include -Recurse:$Recurse
}
}
}
}
}
当我将结果通过管道传递给 ForEach-Object 以将结果复制到不同的目的地时,一切正常,除了与排除参数匹配的项目外,其他项目都被复制
$source = 'D:\Temp\'
$destination = 'D:\Temp_Copy\'
Get-ChildItem-Recurse -Path $source -Exclude @( '*NotThis*', '*NotThat*' ) | ForEach-Object {
$_ | Copy-Item -Destination ( "$($destination)$($_.FullName.Substring($source.Length))" ) -Force
}
当我将其直接通过管道传输到 Copy-Item commandlet 时,出现空值错误,因为 .Substring() 是在显然为 null
的 $_.FullName 上调用的Get-ChildItem-Recurse -Path $source -Exclude @( '*NotThis*', '*NotThat*' ) |
Copy-Item -Destination ( "$($destination)$($_.FullName.Substring($source.Length))" ) -Force
因为本机命令行开关 Get-ChildItem 确实允许我将其结果通过管道传递给 Copy-Item,我喜欢我自己的自定义函数也能够做到这一点。但是我不明白为什么它不起作用。
使用脚本块将管道输入值动态绑定到参数:
Get-ChildItem ... |Copy-Item -Destination { "$($destination)$($_.FullName.Substring($source.Length))" }
mklement0 的以下回答详细介绍了这种动态绑定(追溯命名为 "delay-bind scriptblocks",或通俗地称为“管道绑定脚本块”):
通常您通过管道将源复制:
$source = 'D:\Temp\'
$destination = 'D:\Temp_Copy\'
get-childitem $source | copy-item -destination $destination -whatif