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.
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:
File
Class & File.Open
MethodFileInfo.OpenText
Method & StreamReader
ClassZipArchive
Class & ZipArchive.CreateEntry
MethodStreamWriter
Classusing namespace System.IO
using namespace System.IO.Compression
Add-Type -AssemblyName System.IO.Compression
try {
# 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'
}
If you're looking to simplify the process demonstrated above, reading a zip archive and replacing the content of zip archive entries, you might find it easier with the PSCompression Module (Disclaimer: I'm the author of this module).
This is how the code would look using the module:
$zip = New-Item 'path\to\test.zip' -ItemType File
Get-ChildItem -Path path\to\jsonfolder -Filter *.json | ForEach-Object {
$entryName = $_.BaseName + '-ToBeDetermined' + $_.Extension
($_ | Get-Content -Raw) -replace 'hello', 'world' |
New-ZipEntry -Destination $zip.FullName -EntryPath $entryName
}