为何PowerShell中join生成的逗号分隔路径无法被Compress-Archive识别?
Compress-Archive Path参数传入逗号分隔路径报错问题
问题背景
官方文档对-Path参数的说明:
-Path
指定要添加到压缩包中的文件路径。若要指定多个路径,使用逗号分隔不同路径。
但按文档方式通过代码生成逗号分隔路径列表传入时,出现路径无效错误,直接在命令行输入相同的路径字符串却能正常执行。
出错代码示例1
$now = Get-Date Write-Host "Zipping logs... $now" $dirZip = @() foreach ($vm in $vms) { $vmName = $vm.name $dirZip += "C:\Scripts\ClientLogs\$vmName" } $currentDate = Get-Date -Format "MM-dd-yyyy" $zipDestinationPath = "C:\Scripts\" + $currentDate + "_Client_Logs.zip" Compress-Archive -Path ($dirZip -join ',') -DestinationPath $zipDestinationPath -Force
错误信息
Compress-Archive : The path 'C:\Scripts\ClientLogs\Client1,C:\Scripts\ClientLogs\Client2,C:\Scripts\ClientLogs\Client3,C:\Scripts\ClientLogs\Client4,C:\Scripts\ClientLogs\Client5' either does not exist or is not a valid file system path. At C:\Scripts\VM Copy Files.ps1:169 char:5 + ... Compress-Archive -Path ($dirZip -join ',') -DestinationPa ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (C:\Scripts\Clie...entLogs\Client5:String) [Compress-Archive], InvalidOperationException + FullyQualifiedErrorId : ArchiveCmdletPathNotFound,Compress-Archive
可正常执行的命令
直接在命令行输入逗号分隔路径即可正常运行:
Compress-Archive -Path C:\Scripts\ClientLogs\Client1,C:\Scripts\ClientLogs\Client2,C:\Scripts\ClientLogs\Client3,C:\Scripts\ClientLogs\Client4,C:\Scripts\ClientLogs\Client5 -DestinationPath C:\temp\test.zip
出错代码示例2(字符串拼接方式)
尝试通过字符串拼接生成路径后传入,同样报错:
$now = Get-Date Write-Host "Zipping logs... $now" foreach ($vm in $vms) { $vmName = $vm.name $dirZip = $dirZip + "C:\Scripts\ClientLogs\$vmName," } $currentDate = Get-Date -Format "MM-dd-yyyy" $zipDestinationPath = "C:\Scripts\" + $currentDate + "_Client_Logs.zip" $dirZip = $dirZip.trimend(",") Compress-Archive -Path $dirZip -DestinationPath $zipDestinationPath -Force
问题原因与解决方案
原因
PowerShell参数解析逻辑差异:
- 直接在命令行写逗号分隔路径时,PowerShell会自动将其拆分为字符串数组,每个元素对应一个路径,符合
-Path参数的多值要求 - 但通过变量传入逗号分隔的字符串时,PowerShell会将整个字符串视为单个路径,系统自然找不到这个包含逗号的不存在路径
解决方案
不需要将数组转成逗号分隔的字符串,直接把路径数组传给-Path参数即可:
修改后的正确代码:
$now = Get-Date Write-Host "Zipping logs... $now" $dirZip = @() foreach ($vm in $vms) { $vmName = $vm.name $dirZip += "C:\Scripts\ClientLogs\$vmName" } $currentDate = Get-Date -Format "MM-dd-yyyy" $zipDestinationPath = "C:\Scripts\" + $currentDate + "_Client_Logs.zip" # 直接传入路径数组,无需join处理 Compress-Archive -Path $dirZip -DestinationPath $zipDestinationPath -Force
更简洁的写法
可以直接通过管道生成路径数组,避免手动循环拼接:
$now = Get-Date Write-Host "Zipping logs... $now" # 直接从vms集合生成路径数组 $dirZip = $vms | ForEach-Object { "C:\Scripts\ClientLogs\$($_.name)" } $currentDate = Get-Date -Format "MM-dd-yyyy" $zipDestinationPath = "C:\Scripts\$currentDate_Client_Logs.zip" Compress-Archive -Path $dirZip -DestinationPath $zipDestinationPath -Force
内容的提问来源于stack exchange,提问作者BarelyAdequateSoftwareTest
相关产品推荐
相关产品推荐

