Include files/folders in zip in powershell upon exact Match

71 Views Asked by At

Below are my files

1. C:\Temp\src\config\1.txt
2. C:\Temp\src\logs\wowconfigls\3.txt

The user wants to include the files/folders that exactly match either canweb.war or config.

Thus, $itemsToInclude = "canweb.war,config"

The below approach creates a zip that includes both 1.txt and 3.txt however, it should not have included 3.txt as it is inside the folder wowconfigls which is not an exact match provided by the user.

Only config should have matched.

# 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    

I understand that Where-Object { $_.FullName -ieq $pattern } or Where-Object { $_.FullName -ilike $pattern } should help but the $pattern needs to be considered comma-separated one at a time.

Can you please suggest how can I achieve an exact match?

1

There are 1 best solutions below

3
On

Let's start with this: $pattern = $itemsToInclude.Split(',').ForEach({ [regex]::Escape($_) }) -join '|'

This gives you: $pattern = "canweb\.war|config"

This pattern will return *canweb.war* and *config* since -match looks for the exact part of the string that matches. It's likely canweb.war will be the last part of the file path (FullName) and be okay.

What you need to change is to make the pattern string include more details.

$pattern = "\\canweb\.war$|\\config\\" should return the correct files your looking for.

canweb.war would always appear at the end of the FullName attribute, so using $ to indicate that string should have what we are looking for at the end. For \\config\\, we escape the folder path to match the folder itself. Although this will match startingpath\config\*, so sub-folders would be included too.

EDIT: If the pattern needs to be generated from a CLI parameter $pattern = $itemsToInclude.Split(',').ForEach({if($_.contains('.')){[regex]::Escape($_+"$");} else { [regex]::Escape("\"+$_+"\"); } }) -join '|' would work a little better. Single words would be treated as a folder and file.ext will see the . and add $ to the end to indicate it's a file.