Home > database >  Modify and ZIP file in one statement
Modify and ZIP file in one statement

Time:07-05

PSVersion 5.1.18362.2212

I would like to know if it is possible to read in a set of text files, modify their content and their filenames and store the results directly into a ZIP file?

The following reads text files in and modifies them, storing the change into a new file:

$xSource = "sourcefile.json"
$xTarget = "targetfile.json"
$replacement = "abc"
(Get-Content $xSource) | Foreach-Object {
  $_.replace('[XX]', $replacement).`
} | Set-Content -path $xTarget

Is it possible to modify this to store the target file directly into a ZIP file?

I was hoping something like the following would work, but I am unsure of how I can pass the new filename through to the ZIP? or whether the following works at all?

$xSource = "sourcefile.json"
$xTarget = "targetfile.json"
$xTargetZip = "target.zip"
$replacement = "abc"
(Get-Content $xSource) | Foreach-Object {
  $_.replace('[XX]', $replacement).`
} | Compress-Archive -Update -DestinationPath $xTargetZip

I get the impression that I would need to store the target files into a temporary folder and then pack them from there ... is there any way of avoiding a temporary folder?

Thanks in advance for any and all help.

CodePudding user response:

The solution to this is cumbersome but you asked for it, this is how you can write entries to a zip file without prior writing the updates of your Jsons to new files, in other words, having the contents of the files in memory and writing them to a zip entry.

References for the .NET Docs used here:

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

try {
    Add-Type -AssemblyName System.IO.Compression

    # be aware, DO NOT use relative paths here!
    $DestinationPath = 'path\to\test.zip'
    $destfs = [File]::Open($DestinationPath, [FileMode]::CreateNew)
    $zip    = [ZipArchive]::new($destfs, [ZipArchiveMode]::Update)

    Get-ChildItem -Path path\to\jsonfolder -Filter *.json | ForEach-Object {
        # `OpenText` uses UTF8 encoding, normally there shouldn't be any issues here
        # but you can also use `Get-Content` instead to get the file content
        $reader    = $_.OpenText()
        $content   = $reader.ReadToEnd() -replace 'hello', 'world'
        # this is yours to define, this is how each entry should be named
        $entryName = $_.BaseName   '-ToBeDetermined'   $_.Extension
        $zipEntry  = $zip.CreateEntry($entryName)
        $zipStream = $zipEntry.Open()
        $writer    = [StreamWriter]::new($zipStream)
        $writer.Write($content)
        $writer, $reader, $zipStream | ForEach-Object 'Dispose'
    }
}
finally {
    $zip, $destfs | ForEach-Object 'Dispose'
}
  • Related