Home > Software engineering >  PowerShell CompressArchive -Update into directory inside the zip file
PowerShell CompressArchive -Update into directory inside the zip file

Time:11-23

I'm trying to write a PowerShell script to update a file inside of a zip file, as I need to automate this for a number of zips. My issue is that the file I need to update is inside a few directories inside the zip, such as:

myZip.zip -> dir1/dir2/file.txt

I'm trying to use the command such as

Compress-Archive -Path .\file.txt -Update -DestinationPath .\myZip.zip

But when I run that, the file gets added to the root of the zip file, rather than into the dir1/dir2/ directory as I need it to.

Is this possible?

CodePudding user response:

Worked out that the -Path must reference the same directory structure as it is found in zip file.

My test zip has the following directory structure:

myZip.zip
-> dir1
-> -> dir2
-> -> -> dir3
-> -> -> -> myFile.txt

My reference directory is then defined as:

dir1
-> dir2
-> -> dir3
-> -> -> myFile.txt

I can then run

Compress-Archive -Path .\dir1 -DestinationPath .\myZip.zip -Update

And this puts the file into the right directory.

Thanks to @SantiagoSquarzon here, and @metablaster on a related ticket

CodePudding user response:

This is how you can update the ZipArchiveEntry using the .NET APIs directly, this method doesn't have a need on external applications or Compress-Archive. It also doesn't need to emulate the Zip structure to target the right file, instead, it needs you to target the right Zip Entry by passing the correct relative path (dir1/dir2/dir3/myFile.txt) as argument of .GetEntry(..).

using namespace System.IO
using namespace System.IO.Compression

Add-Type -AssemblyName System.IO.Compression

$filestream = (Get-Item .\myZip.zip).Open([FileMode]::Open)
$ziparchive = [ZipArchive]::new($filestream, [ZipArchiveMode]::Update)
# relative path of the ZipEntry must be precise here
# ZipEntry path is relative, note the forward slashes are important
$zipentry   = $ziparchive.GetEntry('dir1/dir2/dir3/myFile.txt')
$wrappedstream = $zipentry.Open()
# this is the source file, used to replace the ZipEntry
$copyStream    = (Get-Item .\file.txt).OpenRead()
$copyStream.CopyTo($wrappedstream)
$wrappedstream, $copyStream, $ziparchive, $filestream | ForEach-Object Dispose
  • Related