|
<# |
|
BV-ZipUtility.ps1 |
|
http://www.bryanvine.com/2017/03/powershell-script-7zipunzip-powershell.html |
|
|
|
Author: Bryan Vine |
|
|
|
Last updated: 03/27/2017 |
|
|
|
Description: This collection of functions can be used as a module or imported in other |
|
modules to replace most of the functionality of 7zip.exe and unzip.exe. |
|
#> |
|
|
|
#Requires -version 3 |
|
|
|
|
|
|
|
Function Test-DotNet{ |
|
<# |
|
.SYNOPSIS |
|
Checks for a specific .NET framework |
|
.DESCRIPTION |
|
Uses registry keys to find all installed versions of .NET framework and check that the highest version is |
|
greater than or equal to a minimum level. Returns true if it is, false if it isn't. |
|
.PARAMETER MinLevel |
|
Minimum level of .NET framework required to return true. |
|
.EXAMPLE |
|
Test-DotNet |
|
This will return true if .NET 4.5 or greater is installed. |
|
.EXAMPLE |
|
Test-DotNet -MinLevel 4.0 |
|
This will return true if .NET 4.0 or greater is installed. |
|
.LINK |
|
http://www.bryanvine.com/2017/03/powershell-script-7zipunzip-powershell.html |
|
.NOTES |
|
Author: Bryan Vine |
|
Last updated: 03/27/2017 |
|
#> |
|
[cmdletbinding()] |
|
Param( |
|
$MinLevel = 4.5 |
|
) |
|
|
|
((Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -Recurse | |
|
Get-ItemProperty -name Version -ErrorAction SilentlyContinue | |
|
Where {$_.PSChildName -match '^(?!S)\p{L}'} | |
|
Select -ExpandProperty Version -Unique | |
|
Sort -Descending | Select -First 1) -ge $MinLevel) |
|
} |
|
|
|
|
|
|
|
function Compress-toZip{ |
|
<# |
|
.SYNOPSIS |
|
Compresses files and folders into a zip archive. |
|
.DESCRIPTION |
|
Creates new a new archive or updates an existing archive from either an array of files or a directory (or array of directories). |
|
Requires powershell v3+ and .NET 4.5 framework. |
|
.PARAMETER Zipfile |
|
Output name of new zip archive or existing name of archive. Full local path or UNC path prefered for best results. |
|
.PARAMETER Source |
|
Input File(s) or Directory/Directories which are to be compressed into the archive |
|
.PARAMETER CompressionLevel |
|
Amount of compression to apply. Greatest to least: 'Optimal','Fastest','NoCompression' |
|
.PARAMETER IncludeBaseDirectory |
|
Specifies when creating new zip archive to include the base folder when specifying an input directory. |
|
.PARAMETER OverwriteZip |
|
If an existing output zip archive exists, it will delete it first before creating a new one. |
|
.EXAMPLE |
|
Compress-toZip -Zipfile 'test.zip' -Source 'Backup' |
|
This will create a new zip file called test.zip in the current directory with the contents of the Backup folder. |
|
.EXAMPLE |
|
Compress-toZip -Zipfile 'c:\temp\test.zip' -Source '\\server1\Backup' |
|
This will create a new zip file called test.zip in c:\temp with the contents of the Backup share from Server1. |
|
.LINK |
|
http://www.bryanvine.com/2017/03/powershell-script-7zipunzip-powershell.html |
|
.NOTES |
|
Author: Bryan Vine |
|
Last updated: 03/27/2017 |
|
#> |
|
[cmdletbinding()] |
|
Param( |
|
[ValidateNotNullorEmpty()][Parameter(Position=0,Mandatory)][String]$Zipfile, |
|
[ValidateScript({Test-Path $_})][Parameter(Position=1,Mandatory)][String[]]$Source, |
|
[Validateset('Optimal','Fastest','NoCompression')]$CompressionLevel = 'Optimal', |
|
[switch]$IncludeBaseDirectory, |
|
[switch]$OverwriteZip |
|
) |
|
|
|
#Check for .NET 4.5+ |
|
if(!(Test-DotNet)){ |
|
Write-Error "ERROR: Unable to perform zip operation, .NET 4.5+ not detected!" |
|
return 1 |
|
} |
|
|
|
[Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem") | Out-Null |
|
|
|
#Input Normalization |
|
if($Zipfile -notlike '*.zip'){$Zipfile += '.zip'} |
|
if($Zipfile -notlike '*\*'){$Zipfile = $pwd.Path + '\' + $Zipfile} |
|
if($Zipfile -like '.\*'){$Zipfile = $pwd.Path + $Zipfile.Substring(1)} |
|
|
|
#Update existing Zip |
|
if((Test-Path $Zipfile) -and !$OverwriteZip){ |
|
Write-Verbose "Updating existing zip file" |
|
$zip = [System.IO.Compression.ZipFile]::Open($Zipfile,"Update") |
|
|
|
#Remove existing files which will be updated in zip |
|
$SourceFiles = dir -Recurse $Source |?{$_.mode -notlike "d*"}| select -ExpandProperty fullname |
|
$Overlapfiles = $SourceFiles | %{$_.replace(($Source + '\'),'')} |
|
$duplicates = $zip.Entries | ?{$Overlapfiles -contains $_.FullName} |
|
$duplicates | %{$_.Delete()} |
|
|
|
$SourceFiles | %{ |
|
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($Zip, $_, ($_.replace(($Source + '\'),'')), |
|
($CompressionLevel)) | Out-Null |
|
} |
|
$zip.dispose() |
|
|
|
#New or overwrite zip completely |
|
}else{ |
|
#Overwrite |
|
if($OverwriteZip){Remove-Item $Zipfile -Verbose} |
|
|
|
#Source is a directory |
|
if(test-path $Source -PathType Container){ |
|
$Source = dir $Source | select -First 1 -ExpandProperty PSParentPath | %{$_.Replace('Microsoft.PowerShell.Core\FileSystem::','')} |
|
[System.IO.Compression.ZipFile]::CreateFromDirectory($Source, $Zipfile, |
|
([System.IO.Compression.CompressionLevel]::$CompressionLevel), $IncludeBaseDirectory) |
|
|
|
#Source is a single file |
|
}else{ |
|
$zip = [System.IO.Compression.ZipFile]::Open($Zipfile,"Update") |
|
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($Zip, $Source, (dir $Source|select -ExpandProperty name), |
|
($CompressionLevel)) |
|
$zip.dispose() |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
function Expand-fromZip{ |
|
<# |
|
.SYNOPSIS |
|
Expands files and folders from a zip archive. |
|
.DESCRIPTION |
|
Extracts files and folders from a zip file to a selected destination folder. UNC paths work also. |
|
Requires powershell v3+ and .NET 4.5 framework. |
|
.PARAMETER Zipfile |
|
Output name of new zip archive or existing name of archive. Full local path or UNC path prefered for best results. |
|
.PARAMETER Destination |
|
Extration folder or path. UNC also supported. If the destination path doesn't exist, it will be created. |
|
.EXAMPLE |
|
Expand-fromZip -Zipfile 'test.zip' -Destination 'Restored_Backup' |
|
This will extra the contents from test.zip into the folder Restored_Backup. If the folder doesn't exist, it will be created. |
|
.EXAMPLE |
|
Expand-fromZip -Zipfile 'c:\temp\test.zip' -Destination '\\server1\Backup' |
|
This will extract the contents of the zip file called test.zip in c:\temp to the Backup share from Server1. |
|
.LINK |
|
http://www.bryanvine.com/2017/03/powershell-script-7zipunzip-powershell.html |
|
.NOTES |
|
Author: Bryan Vine |
|
Last updated: 03/27/2017 |
|
#> |
|
[cmdletbinding()] |
|
Param( |
|
[ValidateScript({Test-Path $_})][Parameter(Position=0,Mandatory)][String]$Zipfile, |
|
[Parameter(Position=1)][String]$Destination |
|
) |
|
|
|
#Check for .NET 4.5+ |
|
if(!(Test-DotNet)){ |
|
Write-Error "ERROR: Unable to perform zip operation, .NET 4.5+ not detected!" |
|
return 1 |
|
} |
|
|
|
[Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem") | Out-Null |
|
|
|
if(!($Destination)){ |
|
$Destination = $PWD |
|
} |
|
|
|
if(!(Test-Path $Destination)){ |
|
$Destination = (New-Item $Destination -ItemType Directory).FullName |
|
} |
|
|
|
if($Destination -notlike "*\*" -or $Destination -like ".\*"){ |
|
$Destination = dir $PWD | ?{$_.name -like $Destination -or $_.name -like $Destination.replace('.\','')} | select -ExpandProperty FullName |
|
|
|
#select -First 1 -ExpandProperty PSParentPath | %{$_.Replace('Microsoft.PowerShell.Core\FileSystem::','')} |
|
} |
|
|
|
[System.IO.Compression.ZipFile]::ExtractToDirectory($Zipfile, $Destination) |
|
} |
|
|
|
|
|
|
|
Function Invoke-SevenZip{ |
|
<# |
|
.SYNOPSIS |
|
Wrapper function which calls both Compress-toZip and Expand-fromZip |
|
.DESCRIPTION |
|
This function effectively translates the parameters that overlap with both 7z.exe and unzip.exe. |
|
Using the set-alias cmdlets, you can assign this function to '7z' and 'unzip' for easy substitution. |
|
|
|
.PARAMETER CommandMode |
|
Specifies which operation to apply. 'u' or 'a' specify compress, 'x' or 'e' specify expand. |
|
|
|
.PARAMETER CompressionLevel |
|
This sets the level of compression. The native .NET extensions only support 3 levels of compression. |
|
|
|
.PARAMETER ZipFile |
|
Specifies the zip file name to extract from or compress to. |
|
|
|
.PARAMETER Directory |
|
Specifies the directory (or source file) to compress from or extract to. |
|
|
|
.PARAMETER Recurse |
|
This switch enables recursion for compressing a target directory. |
|
|
|
.EXAMPLE |
|
Invoke-SevenZip a 'c:\temp\test.zip' '\\server\share\data' -m 3 |
|
This example compresses the contents of the data folder on server using the highest compression into the test.zip file locally. |
|
|
|
.EXAMPLE |
|
Invoke-SevenZip x 'c:\temp\test.zip' '.\bob' |
|
This extracts the contents of test.zip into a folder named bob in the current directory. |
|
|
|
.LINK |
|
http://www.bryanvine.com/2017/03/powershell-script-7zipunzip-powershell.html |
|
.LINK |
|
Compress-toZip |
|
.LINK |
|
Expand-fromZip |
|
.NOTES |
|
Author: Bryan Vine |
|
Last updated: 03/27/2017 |
|
#> |
|
[cmdletbinding()] |
|
Param( |
|
[Validateset('a','e','u','x')][Parameter(Position=0,Mandatory)][String]$CommandMode, |
|
[Parameter(Position=1,Mandatory)][String]$ZipFile, |
|
[Parameter(Position=2)][String[]]$Directory, |
|
[Validateset('5','4','3','2','1','0','Optimal','Fastest','NoCompression')][Alias("m")]$CompressionLevel = 'Optimal', |
|
[Alias("r")][Switch]$Recurse |
|
|
|
) |
|
|
|
switch($CompressionLevel){ |
|
"5" {$CompressionLevel = 'Optimal'} |
|
"4" {$CompressionLevel = 'Optimal'} |
|
"3" {$CompressionLevel = 'Optimal'} |
|
"2" {$CompressionLevel = 'Optimal'} |
|
"1" {$CompressionLevel = 'Fastest'} |
|
"0" {$CompressionLevel = 'NoCompression'} |
|
} |
|
|
|
if(!($Directory)){ |
|
$Directory = $PWD |
|
} |
|
|
|
if($CommandMode -like 'u' -or $CommandMode -like 'a'){ |
|
Compress-toZip -Zipfile $ZipFile -Source $Directory -CompressionLevel $CompressionLevel |
|
} |
|
|
|
if($CommandMode -like 'e' -or $CommandMode -like 'x'){ |
|
Expand-fromZip -Zipfile $ZipFile -Destination $Directory |
|
} |
|
} |
|
Set-Alias -Name '7z' -Value 'Invoke-SevenZip' |
|
Set-Alias -Name 'Unzip' -Value 'Invoke-SevenZip' |
|
|