Is it possible to create a zip archive using PowerShell?
Is it possible to create a zip archive using PowerShell?
If you head on over to CodePlex and grab the PowerShell Community Extensions, you can use their write-zip cmdlet.
Since
CodePlex is in read-only mode in preparation for shutdown
you can go to PowerShell Gallery.
Lot has changed since the initial answer was posted. Here are some of the latest examples using Compress-Archive command.
Command to create new archive file, Draft.zip, by compressing two files, Draftdoc.docx and diagram2.vsd, specified by the Path parameter. The compression level specified for this operation is Optimal.
Compress-Archive -Path C:\Reference\Draftdoc.docx, C:\Reference\Images\diagram2.vsd -CompressionLevel Optimal -DestinationPath C:\Archives\Draft.Zip
Command to creates new archive file, Draft.zip, by compressing two files, Draft doc.docx and Diagram [2].vsd, specified by the LiteralPath parameter. The compression level specified for this operation is Optimal.
Compress-Archive -LiteralPath 'C:\Reference\Draft Doc.docx', 'C:\Reference\Images\Diagram [2].vsd' -CompressionLevel Optimal -DestinationPath C:\Archives\Draft.Zip
Command to create new archive file, Draft.zip, in the C:\Archives folder. The new archive file contains every file in the C:\Reference folder, because a wildcard character was used in place of specific file names in the Path parameter.
Compress-Archive -Path C:\Reference\* -CompressionLevel Fastest -DestinationPath C:\Archives\Draft
Command creates an archive from an entire folder, C:\Reference
Compress-Archive -Path C:\Reference -DestinationPath C:\Archives\Draft
PowerShell appends the .zip extension to the file name automatically.
Why does no one look at the documentation? The same .NET 4.5 library everyone is referencing lets you do anything you want, including creating an empty ZIP and adding individual files to it.
See below for a code example:
# Load the .NET assembly
Add-Type -Assembly 'System.IO.Compression'
Add-Type -Assembly 'System.IO.Compression.FileSystem'
# Must be used for relative file locations with .NET functions instead of Set-Location:
[System.IO.Directory]::SetCurrentDirectory('.\Desktop')
# Create the zip file and open it:
$z = [System.IO.Compression.ZipFile]::Open('z.zip', [System.IO.Compression.ZipArchiveMode]::Create)
# Add a compressed file to the zip file:
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($z, 't.txt', 't.txt')
# Close the file
$z.Dispose()
Here's an overview on how to manipulate the zip archive while you're at it (just remember to close the file afterwards):
CreateEntryFromFile(...).ZipArchiveEntry. This object lets you inspect the zipped file afterwards including letting you report the .CompressedLength, view or change the .LastWriteTime (needs Update mode), and more below..Entries property, and use the methods above as well as view the filename, the full path, the decompressed size, or delete the file (needs Update mode)..Entries or .GetEntry(...)). You can also extract an archive by its filename alone..Entries or .GetEntry(...)), which would let you do everything in-memory.I encourage you to browse the documentation because that's how I found all this.
For compression, I would use a library (7-Zip is good like Michal suggests).
If you install 7-Zip, the installed directory will contain 7z.exe which is a console application.
You can invoke it directly and use any compression option you want.
If you wish to engage with the DLL, that should also be possible.
7-Zip is freeware and open source.
This is really obscure but works. 7za.exe is standalone version of 7zip and is available with install package.
# get files to be send
$logFiles = Get-ChildItem C:\Logging\*.* -Include *.log | where {$_.Name -match $yesterday}
foreach ($logFile in $logFiles)
{
Write-Host ("Processing " + $logFile.FullName)
# compress file
& ./7za.exe a -mmt=off ($logFile.FullName + ".7z") $logFile.FullName
}
function Zip-File
{
param (
[string]$ZipName,
[string]$SourceDirectory
)
Add-Type -Assembly System.IO.Compression.FileSystem
$Compress = [System.IO.Compression.CompressionLevel]::Optimal
[System.IO.Compression.ZipFile]::CreateFromDirectory($SourceDirectory,
$ZipName, $Compress, $false)
}
Note:
ZipName: Full Path of the Zip File which you want to create.
SourceDirectory: Full path to the directory containing the files which you would like to zip.
Loading the [System.IO.IOException] class and using its methods is an important step in order to suppress unwanted errors, due the fact that it's a class not native to PowerShell, so expect various contexts of errors without it.
I error-controlled my script to the T, but got a lot of extra red 'file exists' output while using [System.IO.Compression.ZipFile] class
function zipFiles(
[Parameter(Position=0, Mandatory=$true]
[string] $sourceFolder,
[Parameter(Position=1, Mandatory=$true]
[string]$zipFileName,
[Parameter(Position=2, Mandatory=$false]
[bool]$overwrite)
{
Add-Type -Assembly System.IO
Add-Type -Assembly System.IO.Compression.FileSystem
$compressionLevel = [System.IO.Compression.CompressionLevel]::Optimal
$directoryTest = (Test-Path $dailyBackupDestFolder)
$fileTest = (Test-Path $zipFileName)
if ( $directoryTest -eq $false)
{
New-Item -ItemType Directory -Force -Path $dailyBackupDestFolder
}
if ( $fileTest -eq $true)
{
if ($overwrite -eq $true ){Remove-Item $zipFileName}
}
try
{
[System.IO.Compression.ZipFile]::CreateFromDirectory($sourceFolder,$zipFileName,$compressionLevel)
}
catch [System.IO.IOException]
{
Write-Output ($dateTime + ' | ' + $_.Exception.Message ) | Out-File $logFile -append -force
}
}
What I am doing here is catching these IO Errors, such as accessing files that exist already, catching that error and directing it to a logfile that I am maintaining with a larger program.
Complete command-line Commands in Windows for Compressing and Extracting Directory is as follows:
For Compression:
powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::CreateFromDirectory('C:\Indus','C:\Indus.zip'); }"
For Extracting:
powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem';[IO.Compression.ZipFile]::ExtractToDirectory('C:\Indus.zip','C:\Indus'); }"
Old thread but still, I got here :)
It is not an answer to the original question, but maybe someone will find it useful how to create ZipArchive object with PS.
# Example, if you have like I have a $myByteArray byte[] with the compressed data:
Add-Type -AssemblyName System.IO.Compression.FileSystem
# Fixed length stream:
$strm = New-Object -TypeName System.IO.MemoryStream -ArgumentList @(, $myByteArray);
# Create ZipArchive object
$arch = [System.IO.Compression.ZipArchive]::new($strm);
# List entries
$arch.Entries