虽然这可能是重复的,但这是不同的。
我已经编写了一个脚本来使用 PowerShell 快速删除包含大量文件和子文件夹的文件夹,现在我将发布我是如何实现并行处理的,并设置一些示例:
功能:
function Parallel-Delete {
param(
[Parameter(Valuefrompipeline=$true, Mandatory=$true, Position=0)] [array]$filelist,
[Parameter(Valuefrompipeline=$true, Mandatory=$true, Position=1)] [int]$number
)
0..($filelist.count-1) | Where-Object {$_ % 16 -eq $number} | foreach {Remove-Item -Path $filelist[$_]}
}
制作一个测试文件夹并列出内容:
$test=[string]"C:\test"+$(get-random)
md $test | out-null
0..10000 | % {ni "${test}\${_}.txt"}|out-null
[array]$filelist=(Get-Childitem -Path $test -File -Force).Fullname
测试1:
0..15 | foreach-object {Invoke-Command -ScriptBlock { Parallel-Delete $filelist $_}}
rd $test
我已经确认并行进程正在工作,但并行进程使用与单线程进程相同数量的资源:
Test2(在运行新测试之前重新制作测试文件夹):
(Get-Childitem -Path $test -File -Force).Fullname | Foreach {Remove-Item -Path $_}
rd $test
而16个并行进程的删除速度并没有想象中单线程进程的16倍,结果如下:
测试1:
PS C:\Windows\System32>Measure-Command {0..15 | foreach-object {Invoke-Command -ScriptBlock { Parallel-Delete $filelist $_}}}
Days : 0
Hours : 0
Minutes : 0
Seconds : 36
Milliseconds : 279
Ticks : 362798015
TotalDays : 0.000419905109953704
TotalHours : 0.0100777226388889
TotalMinutes : 0.604663358333333
TotalSeconds : 36.2798015
TotalMilliseconds : 36279.8015
测试2:
PS C:\Windows\System32>Measure-Command {(Get-Childitem -Path $test -File -Force).Fullname | Foreach {Remove-Item -Path $_}}
Days : 0
Hours : 0
Minutes : 0
Seconds : 25
Milliseconds : 980
Ticks : 259802514
TotalDays : 0.000300697354166667
TotalHours : 0.0072167365
TotalMinutes : 0.43300419
TotalSeconds : 25.9802514
TotalMilliseconds : 25980.2514
我已经使用 start-job 进行了尝试:
0..15 | foreach-object {Start-Job -ScriptBlock { Parallel-Delete $filelist $_}}
而且我没有得到我的预期,它成功启动了 16 个实际上什么都不做的作业,所以我把它们全部停止了,我还注意到,“命令”中的变量 $filelist 不是绿色的......所以我没有'不知道函数是否未被识别或变量没有被传递......
而且我尝试了一种我在这里找到的方法: Powershell Start-Process to start Powershell session and pass local variables
有了这个:
$ScriptBlock = {
function Parallel-Delete {...}
}
remake test folder...
$PowerShell=(Get-Process -Id $pid).path
0..15|%{Start-Process -FilePath $PowerShell -ArgumentList "-Command & {$ScriptBlock Parallel-Delete('$filelist $_')}"}
我已经成功启动了 16 个黑色的 PowerShell 控制台 Windows,它们都显示了这个:
cmdlet Parallel-Delete at command pipeline position 1
Supply values for the following parameters:
number:
这意味着数字未通过,但这也意味着 $filelist 已成功传递(也许),我已经确认带有 scriptblock 的启动过程适用于一个变量,但它未能传递多个变量。
我也知道 Invoke-Expression,虽然我还没有尝试过。目前我认为 start-process 方法更像我想要的——如果我能让它工作的话。
就是这样,如何在n个并行进程中运行具有多个参数的自定义函数,并将多个变量传递给进程,并使它们彼此并发、独立、独立地运行,从而使并行进程的执行速度是产生相同结果的单线程进程的速度的 n 倍?
有人会帮助我吗?任何帮助,将不胜感激。我提前说谢谢。
PS 我在 Windows 10 20H2 上使用 PowerShell 7.1 x64。
更新:我已经尝试了 foreach -parallel:
function Parallel-Delete {
param(
[Parameter(Valuefrompipeline=$true, Mandatory=$true, Position=0)] [array]$filelist,
[Parameter(Valuefrompipeline=$true, Mandatory=$true, Position=1)] [int]$number
)
0..($filelist.count-1) | Where-Object {$_ % 16 -eq $number} | foreach {Remove-Item -Path $filelist[$_]}
}
[array]$filelist=(Get-Childitem -Path "C:\test\0" -File -Force).Fullname
0..15|foreach-object -Parallel {
Parallel-Delete $filelist $_
} -ThrottleLimit 16
它给了我 16 次这个错误信息:
Parallel-Delete:
Line |
2 | Parallel-Delete $filelist $_
| ~~~~~~~~~~~~~~~
| The term 'Parallel-Delete' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
所以函数没有被解析,变量也不是绿色的......
现在我已经尝试过:
0..15|foreach-object -Parallel {
-begin {Parallel-Delete {$filelist $_}}
} -ThrottleLimit 16
它只是给了我这个错误:
ParserError:
Line |
2 | -begin {Parallel-Delete {$filelist $_}}
| ~~
| Unexpected token '$_' in expression or statement.
请帮忙...