PowerShell 多线程压缩目录

Udi*_*mar 3 powershell multithreading powershell-4.0

我有一个 rootDir,下面有 3 个目录,我只想压缩每个目录并使用多线程代码监听结果,所以我尝试了以下方法:

Set-Location "C:\test"
$sw = [Diagnostics.Stopwatch]::StartNew()
Get-Job | Remove-Job
$rootDirectory = $PWD
$dirs = $(Get-ChildItem -Path $rootDirectory -Directory).Name
# $dirs = d1, d2, d3
$sb = {
    Param($init)
    Compress-Archive -Path $init -DestinationPath "$init.zip" -CompressionLevel NoCompression
}

$jobs = @()
$dirs | ForEach-Object {
    $jobs += Start-Job -ScriptBlock $sb -ArgumentList $_
}

Wait-Job -Job $jobs | Out-Null
Receive-Job -Job $jobs
Run Code Online (Sandbox Code Playgroud)

我有

路径“d1”不存在或者不是有效的文件系统路径。
    + CategoryInfo : InvalidArgument: (d1:String) [压缩存档],InvalidOperationException
    +FullyQualifiedErrorId:ArchiveCmdletPathNotFound,压缩存档
    + PS 计算机名 : 本地主机

如果我连续运行压缩命令,而不使用Start-Job,一切似乎都有效。

Ans*_*ers 5

这些作业不会从您的脚本继承其工作目录目录。将其Set-Location放入脚本块并将目录作为参数传递:

$rootdir = 'C:\test'
...
$jobs = Get-ChildItem -Path $rootdir -Directory | ForEach-Object {
    Start-Job -ScriptBlock {
        Param($init, $dir)
        Set-Location $dir
        Compress-Archive -Path $init -DestinationPath "${init}.zip" -CompressionLevel NoCompression
    } -ArgumentList $_, $rootdir
}
...
Run Code Online (Sandbox Code Playgroud)

更好的是,传递完整路径作为参数,而不仅仅是名称:

$rootdir = 'C:\test'
...
$jobs = Get-ChildItem -Path $rootdir -Directory | ForEach-Object {
    Start-Job -ScriptBlock {
        Param($init)
        Compress-Archive -Path $init -DestinationPath "${init}.zip" -CompressionLevel NoCompression
    } -ArgumentList $_.FullName
}
...
Run Code Online (Sandbox Code Playgroud)