# encoding: ascii
# api: powershell
# title: New-Zip
# description: PowerZip – PowerShell Module that allows you to zip files
# version: 0.1
# type: function
# author: ChristopheCREMON
# license: CC0
# function: New-Zip
# x-poshcode-id: 2435
# x-derived-from-id: 2436
# x-archived: 2014-10-18T11:40:34
# x-published: 2011-01-04T07:54:00
#
# - SYNOPSIS
# Create a Zip File from any files piped in.
# - DESCRIPTION
# Requires that you have the SharpZipLib installed, which is available from
# http://www.icsharpcode.net/OpenSource/SharpZipLib/
# - NOTES
# File Name : PowerZip.psm1
# Author : Christophe CREMON (uxone) – http://powershell.codeplex.com
# Requires : PowerShell V2
# - PARAMETER Source
# Set the name of the source to zip (file or directory)
# - PARAMETER ZipFile
# Set the name of the zip file to create
# - PARAMETER Recurse
# Browse the source recursively
# - PARAMETER Include
# Include only items you specify
# - PARAMETER Exclude
# Exclude items you specify
# - PARAMETER AbsolutePaths
# Preserve the absolute path name of each item in the zip container
# - PARAMETER DeleteAfterZip
# Delete source items after successful zip
# - EXAMPLE
# New-Zip -Source C:\Temp -ZipFile C:\Archive\Scripts.zip -Include *.ps1 -DeleteAfterZip
# Copies all PS1 files from the C:\Temp directory to C:\Archive\Scripts.zip and delete them after successful ZIP
#
Function New-Zip
{
<#
.SYNOPSIS
Create a Zip File from any files piped in.
.DESCRIPTION
Requires that you have the SharpZipLib installed, which is available from
http://www.icsharpcode.net/OpenSource/SharpZipLib/
.NOTES
File Name : PowerZip.psm1
Author : Christophe CREMON (uxone) - http://powershell.codeplex.com
Requires : PowerShell V2
.PARAMETER Source
Set the name of the source to zip (file or directory)
.PARAMETER ZipFile
Set the name of the zip file to create
.PARAMETER Recurse
Browse the source recursively
.PARAMETER Include
Include only items you specify
.PARAMETER Exclude
Exclude items you specify
.PARAMETER AbsolutePaths
Preserve the absolute path name of each item in the zip container
.PARAMETER DeleteAfterZip
Delete source items after successful zip
.EXAMPLE
New-Zip -Source C:\Temp -ZipFile C:\Archive\Scripts.zip -Include *.ps1 -DeleteAfterZip
Copies all PS1 files from the C:\Temp directory to C:\Archive\Scripts.zip and delete them after successful ZIP
#>
param (
[ValidateNotNullOrEmpty()]
[Parameter(
Mandatory = $true)
]
[string] $Source,
[Parameter(
Mandatory = $true)
]
[string] $ZipFile,
[switch] $Recurse,
[array] $Include,
[array] $Exclude,
[switch] $AbsolutePaths,
[switch] $DeleteAfterZip )
[int] $ExitCode = 1
$LoadAssembly = [System.Reflection.Assembly]::LoadWithPartialName("ICSharpCode.SharpZipLib")
if ( -not $LoadAssembly ) { throw "! Assembly not found {ICSharpCode.SharpZipLib}" }
if ( $ZipFile -notmatch "\.zip$" ) { $ZipFile = $ZipFile -replace "$",".zip" }
if ( $Recurse -eq $true ) { $RecurseArgument = "-Recurse" }
if ( $AbsolutePaths -eq $true ) { $AbsolutePathsArgument = "-AbsolutePaths" }
if ( $DeleteAfterZip -eq $true ) { $DeleteAfterZipArgument = "-DeleteAfterZip" }
if ( $Include )
{
$Include = $Include -join ","
$IncludeArgument = "-Include $Include"
}
if ( $Exclude )
{
$Exclude = $Exclude -join ","
$ExcludeArgument = "-Exclude $Exclude"
}
$RootPath = ( Resolve-Path -Path $Source -ErrorAction SilentlyContinue ).Path
if ( -not $RootPath ) { throw "! Source not found {$Source}" }
if ( $Include ) { $Source = $Source+"\*" }
$GetCommand = "Get-ChildItem -Path '$Source' $RecurseArgument $IncludeArgument $ExcludeArgument -Force"
$ItemsToZip = Invoke-Expression -Command $GetCommand
$SizeBeforeZip = ( $ItemsToZip | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue ).Sum
$SizeBeforeZipInMB = $SizeBeforeZip | ForEach-Object { "{0:N2}" -f ($_ / 1MB) }
if ( -not $SizeBeforeZip )
{
Write-Output "NOTHING TO ZIP"
break
}
$StartTime = Get-Date
Write-Output "`n===================================`n=> Start Time : $($StartTime.ToString(""dd/MM/yyyy-HH:mm:ss""))`n"
Write-Output "TOTAL SIZE BEFORE ZIP : {$SizeBeforeZipInMB MB}`n"
Write-Output "Initializing ZIP File {$ZipFile} ...`n"
$CreateZIPContainer = New-Item -ItemType File -Path $ZipFile -Force -ErrorAction SilentlyContinue
if ( -not $CreateZIPContainer ) { throw "! Unable to create ZIP container {$ZipFile}" }
$oZipOutputStream = New-Object -TypeName ICSharpCode.SharpZipLib.Zip.ZipOutputStream([System.IO.File]::Create($ZipFile))
[byte[]] $Buffer = New-Object Byte[] 4096
foreach ( $Item in $ItemsToZip )
{
if ( $Item.FullName -ne $ZipFile )
{
if ( Test-Path ( $Item.FullName ) -ErrorAction SilentlyContinue )
{
$ZipEntry = $Item.FullName
if ( -not $AbsolutePaths )
{
$ReplacePath = [Regex]::Escape( $RootPath+"\" )
$ZipEntry = $Item.FullName -replace $ReplacePath,""
}
if ( $Item.psIsContainer -eq $true )
{
if ( $Recurse -eq $true )
{
Write-Output "Processing ZIP of Directory {$($Item.FullName)} ..."
$OldErrorActionPreference = $ErrorActionPreference
$ErrorActionPreference = "SilentlyContinue"
$oZipEntry = New-Object -TypeName ICSharpCode.SharpZipLib.Zip.ZipEntry("$ZipEntry/")
$oZipOutputStream.PutNextEntry($oZipEntry)
if ( $? -ne $true )
{
$ItemsNotZipped += @($Item.FullName)
$ErrorsArray += @("! Unable to ZIP Directory {$($Item.FullName)}")
}
$ErrorActionPreference = $OldErrorActionPreference
}
}
else
{
Write-Output "Processing ZIP of File {$($Item.FullName)} ..."
$OldErrorActionPreference = $ErrorActionPreference
$ErrorActionPreference = "SilentlyContinue"
$FileStream = [IO.File]::OpenRead($Item.FullName)
$oZipEntry = New-Object -TypeName ICSharpCode.SharpZipLib.Zip.ZipEntry("$ZipEntry")
$oZipOutputStream.PutNextEntry($oZipEntry)
[ICSharpCode.SharpZipLib.Core.StreamUtils]::Copy($FileStream,$oZipOutputStream,$Buffer)
if ( $? -ne $true )
{
$ItemsNotZipped += @($Item.FullName)
$ErrorsArray += @("! Unable to ZIP File {$($Item.FullName)}")
}
$FileStream.Close()
}
}
}
}
$oZipOutputStream.Finish()
$oZipOutputStream.Close()
if ( $? -eq $true )
{
$ErrorActionPreference = $OldErrorActionPreference
if ( $DeleteAfterZip )
{
$ItemsToZip | Where-Object { $ItemsNotZipped -notcontains $_.FullName } | ForEach-Object {
if ( $_.psIsContainer -ne $true )
{
if ( Test-Path ( $_.FullName ) -ErrorAction SilentlyContinue )
{
Write-Output "Processing Delete of File {$($_.FullName)} ..."
$RemoveItem = Remove-Item -Path $_.FullName -Force -ErrorAction SilentlyContinue
if ( $? -ne $true )
{
$ErrorsArray += @("! Unable to Delete File {$($_.FullName)}")
}
}
}
}
if ( $Recurse )
{
$ItemsToZip | Where-Object { $ItemsNotZipped -notcontains ( Split-Path -Parent $_.FullName ) } | ForEach-Object {
if ( $_.psIsContainer -eq $true )
{
if ( Test-Path ( $_.FullName ) -ErrorAction SilentlyContinue )
{
Write-Output "Processing Delete of Directory {$($_.FullName)} ..."
$RemoveItem = Remove-Item -Path $_.FullName -Force -Recurse -ErrorAction SilentlyContinue
if ( $? -ne $true )
{
$ErrorsArray += @("! Unable to Delete Directory {$($_.FullName)}")
}
}
}
}
}
}
Write-Output "`nZIP File Created {$ZipFile} ...`n"
$ExitCode = 0
}
else
{
$ErrorActionPreference = $OldErrorActionPreference
$ErrorsArray += @("! ZIP Archive {$ZipFile} Creation Failed`n")
}
if ( $ErrorsArray )
{
Write-Output "`n[ ERRORS OCCURED ]"
$ErrorsArray
$ExitCode = 1
}
else
{
$SizeAfterZip = ( Get-Item -Path $ZipFile -Force -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue ).Sum
$SizeAfterZipInMB = $SizeAfterZip | ForEach-Object { "{0:N2}" -f ($_ / 1MB) }
Write-Output "`nTOTAL SIZE AFTER ZIP : {$SizeAfterZipInMB MB}`n"
$Gain = ( $SizeBeforeZip - $SizeAfterZip )
$GainInMB = $Gain | ForEach-Object { "{0:N2}" -f ($_ / 1MB) }
if ( $Gain -gt 0 )
{
$GainInPercent = (($SizeBeforeZip - $SizeAfterZip) / $SizeBeforeZip) * 100 | ForEach-Object { "{0:N2}" -f $_ }
Write-Output "GAIN : {$GainInMB MB} ($GainInPercent %)`n"
}
}
$EndTime = Get-Date
$ExecutionTime = ($EndTime-$StartTime)
Write-Output "`nExecution Time : $ExecutionTime`n"
Write-Output "=> End Time : $($EndTime.ToString(""dd/MM/yyyy-HH:mm:ss""))`n=================================`n"
exit $ExitCode
}
Export-ModuleMember -Function New-Zip