Powershell Script to Zip Files

5,142

Solution 1

You need to download the Powershell Community Extension compatible with your installed Powershell version and install the same. Once the installation is done You need to move the PSCX module from the Program files location to the Powershell Module and then try using Write-Zip command.

https://pscx.codeplex.com/releases/view/133199

Solution 2

Zipping can be done using the CreateFromDirectory method of the .NET class System.IO.Compression.ZipFile. I prefer using .NET over installing community extensions and other add-ons, in order to keep the server environment as clean as possible.

I believe you cannot use it to add to a zip archive, but would need to temporarily copy the files and folders in the correct structure to a staging directory. From there you could create the zip file and delete the staging content.

To use .NET for zipping you first need to load the class assembly:

[System.Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem")

Then you can call the class:

[System.IO.Compression.ZipFile]::CreateFromDirectory($DirPath, $ZipFilePath, $CompressionLevel, $includeBaseDir)

Where:

$DirPath is the directory you want to zip.

$ZipFilePath is the name of the zipfile you want to create.

$Compressionlevel can be set to Optimal, Fastest or NoCompression.

$includeBaseDir can be $true or $false.

I wrote a function out of it to save me the bother of having to look up the .NET reference page all the time. If you look at the page you will see there is a method for unzipping too.

.NET 4.5 is required and I would strongly encourage you to upgrade powershell too. Every version has brought massive improvements. It also turns out using .NET is efficient, having benchmarked it against popular 3rd party zip applications it comes out strongly.

The function is pretty self explanatory, just make sure you run the function itself before calling it. Here is a short syntax rundown if you need it:

New-ZipFile {DirToZip} {ZipfilePathAndName} {fastORoptimalORnocompression} {IncludeBaseDirectoryInZip($true or $false)}

So to zip E:\stuff to D:\zipfile.zip using optimal compression and include the basedir .\stuff in the zipfile, you would run:

New-ZipFile 'E:\stuff' 'D:\zipfile.zip' Optimal $true

Here is the function:

#region function New-ZipFile
<#
.Synopsis
   Creates a zip file from a directory.
.DESCRIPTION
   Creates a zip file from a directory. Options include compression level and wether or not to include the base directory. Class reference: https://msdn.microsoft.com/en-us/library/hh875104(v=vs.110).aspx
.EXAMPLE
   New-ZipFile c:\dir c:\zipfile.zip Fastest $True
.EXAMPLE
   New-ZipFile c:\dir c:\zipfile.zip Optimal $True
.INPUTS
   Inputs to this cmdlet (if any)
.OUTPUTS
   Output from this cmdlet (if any)
.NOTES
   General notes
.COMPONENT
   The component this cmdlet belongs to
.ROLE
   The role this cmdlet belongs to
.FUNCTIONALITY
   The functionality that best describes this cmdlet
#>
function New-ZipFile
{
    Param
    (
        # The directory to zip.
        [Parameter(Mandatory=$true, 
                   Position=0)]
        [ValidateNotNullOrEmpty()]
        [string]$DirPath,

        # The zipfile name.
        [Parameter(Mandatory=$true, 
                   Position=1)]
        [ValidateNotNullOrEmpty()]
        [string]$ZipFilePath,

        # Specifies values that indicate whether a compression operation emphasizes speed or compression size.
        [Parameter(Mandatory=$true, 
                   Position=2)]
        [ValidateNotNullOrEmpty()]
        [ValidateSet("Fastest", "NoCompression", "Optimal", ignorecase=$True)]
        [string]$CompressionLevel,

        # $True to include the directory name from sourceDirectoryName at the root of the archive; $False to include only the contents of the directory.
        [Parameter(Mandatory=$true, 
                   Position=3)]
        [ValidateNotNullOrEmpty()]
        [bool]$includeBaseDir
          )

    #Load the .NET 4.5 zip-assembly
    [System.Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem") | Out-Null
    # Zip the directory.
    [System.IO.Compression.ZipFile]::CreateFromDirectory($DirPath, $ZipFilePath, $CompressionLevel, $includeBaseDir)
}
#endregion

EDIT: The Scripting guy wrote an article where he shows an alternative way of loading the assembly, it's a bit cleaner looking.

Share:
5,142

Related videos on Youtube

user26712
Author by

user26712

Updated on September 18, 2022

Comments

  • user26712
    user26712 over 1 year

    I'm new to Powershell. I have a need that I assumed that it would be perfect for. However, I've quickly come to the point where I feel I'm in over my head. Basically, I need to create a .zip file.

    I have a directory that looks like the following:

    MyStuff
      Dir1
        Child1
          File1.txt
        Child2
          File1.png
        Child3
          File1.txt
      Dir2
        File1.txt
      File1.txt
      File2.txt
      File3.txt
      ...
    

    I need to create a .zip file named bundle.zip. Bundle.zip should NOT have all of the files inside of MyStuff. Instead, I need to include MyStuff/File1.txt, MyStuff/File2.txt, MyStuff/File3.txt, and MyStuff/Dir1/* into the .zip file. I have no idea how to do this with PowerShell.

    I have PowerShell v1.0 installed on my machine. I've been trying "Write-Zip" from the PowerShell Community Extensions, however, I get an error that says: "The term 'Write-Zip' is not recognized as the name of a cmdlet, function, script file, or operable program".

    What am I doing wrong?

    • Etan Reisner
      Etan Reisner almost 11 years
      I'd start by suggesting that you upgrade powershell if you can, v1.0 is relatively old and I believe things have changed rather dramatically between then and now. That being said that error sounds like you just haven't loaded the extension correctly.
    • user26712
      user26712 almost 11 years
      As it turns out, I have version 3 installed. I've confirmed this by running $Host.version from the powershell prompt. For some reason, MS just kept it in the v1.0 direction :/
    • Etan Reisner
      Etan Reisner almost 11 years
      How did you install/load the extension you are trying to use? Does Get-Command Write-Zip find the command? What about Get-Module <the extension module>?
    • user26712
      user26712 almost 11 years
      Get-Command Write-Zip and Get-Module pscx both work from the command line just fine.
    • Etan Reisner
      Etan Reisner almost 11 years
      So in a single powershell session you can run Get-Command Write-Zip and it finds the function but if you then try to run Write-Zip it fails with the error in your post?
    • user26712
      user26712 almost 11 years
      that is correct
    • Etan Reisner
      Etan Reisner almost 11 years
      Can you show the output from Get-Command Write-Zip | select *? I'm not a powershell expert but I don't know, offhand, how get-command could find something that powershell itself has trouble with (unless it is a requirement or something failure that powershell is reporting badly).
    • Joshua McKinnon
      Joshua McKinnon almost 11 years
      I have not used a downloadable module in PowerShell previously, but for other modules (such as the Active-Directory module), they must be imported into your session with Import-Module before the commands can be used. Try: Import-Module Pscx Does it then allow you to use the Write-Zip Cmdlet?
    • Joshua McKinnon
      Joshua McKinnon almost 11 years
      Which version of the PowerShell Community Extensions did you install? v3.0 or the v1.0 compatible version (due to originally thinking you had PowerShell v1.0)?
    • splattered bits
      splattered bits almost 11 years
      Please show us the code you're using to load the Pscx module and use Write-Zip.
  • Ryan Ries
    Ryan Ries almost 9 years
    Emphasis on "compatible with your installed version..." not sure what version of PSCX is compatible with PS v1.0, but it's not the latest one.