PowerShell中实现Zip压缩的精准文件/文件夹匹配需求
问题背景
现有文件列表:
1. C:\Temp\src\config\1.txt 2. C:\Temp\src\logs\wowconfigls\3.txt
用户需求:在PowerShell中创建Zip压缩包时,仅包含完全匹配canweb.war文件或config文件夹下的所有内容,因此设置$itemsToInclude = "canweb.war,config"。
现有问题
当前脚本错误地将3.txt纳入了压缩包,因为该文件所在的wowconfigls文件夹名称包含config子串,但用户要求的是精准匹配config文件夹,仅应包含config文件夹下的文件。
现有脚本及执行结果
脚本代码
# Set the name of the zip file including the build number $zipFileName = "C:\Temp\package-165.zip" cd "C:\Temp" $itemsToInclude = "canweb.war,config" Write-Host "itemsToInclude is- $itemsToInclude" if (-not (Test-Path $zipFileName)) { $null = New-Item $zipFileName -ItemType File } $workspace = "C:\Temp" if ($itemsToInclude -eq '*') { # Include all files, including files from subdirectories Write-Host "Include all files, including files from subdirectories" Get-ChildItem -Path $workspace -Recurse -File | Compress-Archive -DestinationPath $zipFileName -Update -Force } else { # Include specific files as per the comma-separated list Write-Host 'Include specific files as per the comma-separated list' $pattern = $itemsToInclude.Split(',').ForEach({ [regex]::Escape($_) }) -join '|' Write-Host "PATTERN is: $pattern" $filesToInclude = Get-ChildItem $workspace -Recurse -File | Where-Object FullName -Match $pattern #$filesToInclude = Get-ChildItem $workspace -Recurse -File | Where-Object { $_.FullName -eq $pattern } #Where-Object { $_.FullName -eq $pattern } #Where-Object FullName -eq $pattern $filesToInclude | ForEach-Object { $newZipEntrySplat = @{ EntryPath = $_.FullName.Substring($workspace.Length) SourcePath = $_.FullName Destination = $zipFileName } New-ZipEntry @newZipEntrySplat } #Compress-Archive -DestinationPath $zipFileName -Update }
执行结果
itemsToInclude is- canweb.war,config Include specific files as per the comma-separated list PATTERN is: canweb\.war|config Directory: src/config/ EntryType LastWriteTime CompressedSize Size EntryName --------- ------------- -------------- ---- --------- Archive 12/6/2023 7:43 AM 9.00 B 7.00 B 1.rtf Archive 12/6/2023 7:43 AM 0.00 B 0.00 B 2.docx Directory: src/logs/wowconfigls/ EntryType LastWriteTime CompressedSize Size EntryName --------- ------------- -------------- ---- --------- Archive 12/6/2023 7:43 AM 0.00 B 0.00 B 3.txt
需求咨询
已知使用Where-Object { $_.FullName -ieq $pattern }或Where-Object { $_.FullName -ilike $pattern }可能实现精准匹配,但需对逗号分隔的匹配项逐一处理,请问如何实现该精准匹配需求?
解决方案
要实现精准匹配,需分别处理文件和文件夹两种匹配场景,避免子串误匹配。核心思路是拆分匹配项后,逐个判断文件是否符合以下任一条件:
- 文件名完全匹配目标文件(如
canweb.war) - 文件位于精准匹配的目标文件夹(如
config)或其子目录下
修改后的完整脚本
# Set the name of the zip file including the build number $zipFileName = "C:\Temp\package-165.zip" cd "C:\Temp" $itemsToInclude = "canweb.war,config" Write-Host "itemsToInclude is- $itemsToInclude" if (-not (Test-Path $zipFileName)) { $null = New-Item $zipFileName -ItemType File } $workspace = "C:\Temp" if ($itemsToInclude -eq '*') { # Include all files, including files from subdirectories Write-Host "Include all files, including files from subdirectories" Get-ChildItem -Path $workspace -Recurse -File | Compress-Archive -DestinationPath $zipFileName -Update -Force } else { # Include specific files as per the comma-separated list Write-Host 'Include specific files as per the comma-separated list' # 拆分并清理匹配项,去除多余空格 $includeItems = $itemsToInclude.Split(',') | ForEach-Object { $_.Trim() } $filesToInclude = Get-ChildItem $workspace -Recurse -File | Where-Object { $currentFile = $_ # 遍历每个匹配项,满足任一条件则保留该文件 $includeItems | ForEach-Object { $targetItem = $_ # 场景1:文件名完全匹配目标文件 if ($currentFile.Name -eq $targetItem) { return $true } # 场景2:文件位于精准匹配的目标文件夹下 $targetFolder = Join-Path $workspace $targetItem # 检查文件路径是否以目标文件夹路径开头,确保是精准目录下的内容 if ($currentFile.FullName.StartsWith($targetFolder, [System.StringComparison]::OrdinalIgnoreCase)) { return $true } } # 无匹配项则排除 return $false } $filesToInclude | ForEach-Object { $newZipEntrySplat = @{ EntryPath = $_.FullName.Substring($workspace.Length) SourcePath = $_.FullName Destination = $zipFileName } New-ZipEntry @newZipEntrySplat } }
关键说明
- 使用
Join-Path构造目标文件夹路径,避免手动拼接路径时的分隔符错误 - 通过
StartsWith判断文件是否在目标文件夹或其子目录下,彻底避免名称包含config的其他文件夹被误匹配 - 文件名匹配使用精准的
-eq运算符,确保只有完全同名的文件被纳入
内容的提问来源于stack exchange,提问作者Ashar
相关产品推荐
相关产品推荐

