如何使用PowerShell的Compress-Archive实现多线程批量压缩多个文件夹
多线程批量压缩脚本实现
核心逻辑说明
完全保留原有脚本逻辑:自动排除Enter开头的目录、检测目录下是否已有zip包避免重复压缩,新增并发控制参数,可根据设备性能自行调整同时执行的压缩任务数量。
版本1:PowerShell 7+ 适用(语法简洁性能最优)
# 打开文件夹选择对话框 function Select-Folder { Add-Type -AssemblyName System.Windows.Forms $folderDialog = New-Object System.Windows.Forms.FolderBrowserDialog $folderDialog.Description = "请选择待处理的根目录" $result = $folderDialog.ShowDialog() if ($result -eq [System.Windows.Forms.DialogResult]::OK) { return $folderDialog.SelectedPath } return $null } function Zip-Folders { param( [String]$FolderPath, [int]$MaxParallel = 8 # 可自行调整最大并行任务数,建议和CPU物理核心数保持一致 ) if ([string]::IsNullOrEmpty($FolderPath)) { $FolderPath = Select-Folder if ($null -eq $FolderPath) { return } } # 获取所有待处理目录 $targetFolders = Get-ChildItem -Path $FolderPath -Directory -Exclude Enter* # 并行处理压缩任务 $targetFolders | ForEach-Object -Parallel { $folder = $_ $zipName = "$($folder.Name) Photos.zip" $zipFullPath = Join-Path -Path $folder.FullName -ChildPath $zipName # 检查是否已有压缩包,和原逻辑保持一致,存在任意zip则跳过 if (-not (Get-ChildItem -Path $folder.FullName -Filter *.zip -File | Select-Object -First 1)) { Write-Host "正在压缩:$($folder.FullName)" Compress-Archive -Path (Join-Path $folder.FullName -ChildPath *) -DestinationPath $zipFullPath -Force Write-Host "压缩完成:$zipFullPath" } else { Write-Host "已跳过:$($folder.Name) 已有压缩包" } } -ThrottleLimit $MaxParallel } # 直接调用Zip-Folders即可弹出文件夹选择框 # Zip-Folders
版本2:兼容PowerShell 5.1(Windows系统自带版本适用)
如果不想升级PowerShell,可使用基于RunspacePool的兼容版本,性能远高于单线程执行:
# 打开文件夹选择对话框 function Select-Folder { Add-Type -AssemblyName System.Windows.Forms $folderDialog = New-Object System.Windows.Forms.FolderBrowserDialog $folderDialog.Description = "请选择待处理的根目录" $result = $folderDialog.ShowDialog() if ($result -eq [System.Windows.Forms.DialogResult]::OK) { return $folderDialog.SelectedPath } return $null } function Zip-Folders { param( [String]$FolderPath, [int]$MaxParallel = 8 # 可自行调整最大并行任务数 ) if ([string]::IsNullOrEmpty($FolderPath)) { $FolderPath = Select-Folder if ($null -eq $FolderPath) { return } } # 获取所有待处理目录 $targetFolders = Get-ChildItem -Path $FolderPath -Directory -Exclude Enter* if ($targetFolders.Count -eq 0) { Write-Host "未找到待处理的目录" return } # 初始化RunspacePool $runspacePool = [RunspaceFactory]::CreateRunspacePool(1, $MaxParallel) $runspacePool.Open() $jobs = @() foreach ($folder in $targetFolders) { $powerShell = [PowerShell]::Create() $powerShell.RunspacePool = $runspacePool $powerShell.AddScript({ param($folder) $zipName = "$($folder.Name) Photos.zip" $zipFullPath = Join-Path -Path $folder.FullName -ChildPath $zipName # 检查是否已有压缩包 if (-not (Get-ChildItem -Path $folder.FullName -Filter *.zip -File | Select-Object -First 1)) { Compress-Archive -Path (Join-Path $folder.FullName -ChildPath *) -DestinationPath $zipFullPath -Force return "压缩完成:$zipFullPath" } else { return "已跳过:$($folder.Name) 已有压缩包" } }).AddArgument($folder) $jobs += @{ PS = $powerShell AsyncResult = $powerShell.BeginInvoke() } } # 接收执行结果 foreach ($job in $jobs) { $result = $job.PS.EndInvoke($job.AsyncResult) Write-Host $result $job.PS.Dispose() } # 释放资源 $runspacePool.Close() $runspacePool.Dispose() } # 直接调用Zip-Folders即可弹出文件夹选择框 # Zip-Folders
可查阅的本地参考资料
无需跳转外部网站,直接在PowerShell中执行以下命令即可获取官方说明文档:
- 并行循环相关:
Get-Help ForEach-Object -Parameter Parallel - Runspace概念相关:
Get-Help about_Runspaces - 压缩命令参数:
Get-Help Compress-Archive -Full
内容的提问来源于stack exchange,提问作者zPRAWN
相关产品推荐
相关产品推荐

