Prof. Powershell
PowerShell File Frontier, Part 7: Zipped Files from Scratch
- By Jeffery Hicks
- 10/06/2014
The finale of Prof. PowerShell's 7-part series ends with creating a zipped file.
More on this topic:
I hope you've not only been seeing how to create zip files from PowerShell but also how to discover properties and methods for .NET classes. As you should have picked up from the last article, it is also very important to at least try to read through any documentation you can find. We have been working with existing zip archives. Today, let's create one from scratch
The [System.IO.Compression.ZipFile] class has a method called CreateFromDirectory().
PS C:\> [System.IO.Compression.ZipFile].getmethods().Name | get-unique
OpenRead
Open
CreateFromDirectory
ExtractToDirectory
ToString
Equals
GetHashCode
GetType
Using the techniques I've taught you , here's how to use it.
PS C:\> [System.IO.Compression.ZipFile]::CreateFromDirectory.OverloadDefinitions
static void CreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName)
static void CreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName, System.IO.Compression.
CompressionLevel compressionLevel, bool includeBaseDirectory)
static void CreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName, System.IO.Compression.
CompressionLevel compressionLevel, bool includeBaseDirectory, System.Text.Encoding entryNameEncoding)
I'm willing to test it out:
PS C:\> [System.IO.Compression.ZipFile]::CreateFromDirectory("c:\work",
"c:\zip\mywork.zip","optimal",$True)
That last value, $True, will include C:\work which is what I want. Notice that when we've been invoking methods, there is no support for –WhatIf or –Confirm. That's one of the disadvantages of using a .NET class instead of a cmdlet.
Next, let's turn around and open the file in PowerShell.
PS C:\> $zip = [System.IO.Compression.ZipFile]::OpenRead("c:\zip\mywork.zip")
PS C:\> $zip.entries.count
118
PS C:\> $zip.entries[0]
Archive : System.IO.Compression.ZipArchive
CompressedLength : 166
FullName : work\admins.csv
LastWriteTime : 3/5/2014 2:14:42 PM -05:00
Length : 449
Name : admins.csv
Did you notice that the fullname includes the Work path? That's because I included it when I built the archive. It isn't too much more work to quickly report on the contents.
PS C:\> [pscustomobject]@{
Count=$zip.entries.count
TotalSize=($zip.entries | measure length -sum).sum
TotalCompressed=($zip.entries | measure compressedlength -sum).sum
}
Count TotalSize TotalCompressed
----- --------- ---------------
118 28037292 8111399
But let's say you want to archive all of your PowerShell scripts last modified in August 2014. First, I need to have an expression to find all the files.
dir c:\scripts\*.ps1 -recurse | where {$_.LastWriteTime -ge "8/1/2014" -and $_.LastWriteTime -lt "9/1/2014"}
From looking at the ZipFile methods, the Open() method has a parameter that will allow me to create an empty zip file.
$zip = [System.IO.Compression.ZipFile]::Open("c:\zip\August2014.zip","Create")
When the file is open, all I need to do is add an entry for each file. This is a great example for using ForEach-Object.
dir c:\scripts\*.ps1 -recurse |
where {$_.LastWriteTime -ge "8/1/2014" -and $_.LastWriteTime -lt "9/1/2014"} |
foreach -begin {
$zip = [System.IO.Compression.ZipFile]::Open("c:\zip\August2014.zip","Create")
} -process {
#split off the parent path for the entry name
$entry= $_.FullName.Split(":")[1].substring(1)
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip,$_.fullname,
$entry,"optimal")
} -end {
$zip.Dispose()
}
I create a new zip in the Begin scriptblock, add an entry for each file in the Process scriptblock using the directory path for the entry and when finished, close the file.
And there you have it. With a little work you can create some simple archiving scripts using the file system and the compression classes. As you may have seen, there are methods for extracting and removing files from zip archives, but I'll leave those for you to figure out how to use. Hopefully, you've picked up enough techniques over the last few articles.
About the Author
Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, trainer and consultant. Jeff has written for numerous online sites and print publications, is a contributing editor at Petri.com, and a frequent speaker at technology conferences and user groups.