<#
.Synopsis
Expand-ZipFile will extract zip files to the specified location
.DESCRIPTION
Expand-ZipFile will extract a zip file and put the extracted contents in the specified location.
This is the second code block that I have not hand-written
#>
function Expand-ZipFile {
#.Synopsis
# Expand a zip file, ensuring it's contents go to a single folder ...
[CmdletBinding()]
param(
# The path of the zip file that needs to be extracted
[Parameter(ValueFromPipelineByPropertyName=$true, Position=0, Mandatory=$true)]
[Alias("PSPath")]
$FilePath,
# The path where we want the output folder to end up
[Parameter(Position=1)]
$OutputPath = $Pwd,
# Make sure the resulting folder is always named the same as the archive
[Switch]$Force
)
process {
Add-Type -Path "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.IO.Compression.FileSystem.dll"
$ZipFile = Get-Item $FilePath
$Archive = [System.IO.Compression.ZipFile]::Open( $ZipFile, "Read" )
# Figure out where we'd prefer to end up
if(Test-Path $OutputPath) {
# If they pass a path that exists, we want to create a new folder
$Destination = Join-Path $OutputPath $ZipFile.BaseName
} else {
# Otherwise, since they passed a folder, they must want us to use it
$Destination = $OutputPath
}
# The root folder of the first entry ...
$ArchiveRoot = ($Archive.Entries[0].FullName -Split "/|\\")[0]
Write-Verbose "Desired Destination: $Destination"
Write-Verbose "Archive Root: $ArchiveRoot"
# If any of the files are not in the same root folder ...
if($Archive.Entries.FullName | Where-Object { @($_ -Split "/|\\")[0] -ne $ArchiveRoot }) {
# extract it into a new folder:
New-Item $Destination -Type Directory -Force
[System.IO.Compression.ZipFileExtensions]::ExtractToDirectory( $Archive, $Destination )
} else {
# otherwise, extract it to the OutputPath
[System.IO.Compression.ZipFileExtensions]::ExtractToDirectory( $Archive, $OutputPath )
# If there was only a single file in the archive, then we'll just output that file...
if($Archive.Entries.Count -eq 1) {
# Except, if they asked for an OutputPath with an extension on it, we'll rename the file to that ...
if([System.IO.Path]::GetExtension($Destination)) {
Move-Item (Join-Path $OutputPath $Archive.Entries[0].FullName) $Destination
} else {
Get-Item (Join-Path $OutputPath $Archive.Entries[0].FullName)
}
} elseif($Force) {
# Otherwise let's make sure that we move it to where we expect it to go, in case the zip's been renamed
if($ArchiveRoot -ne $ZipFile.BaseName) {
Move-Item (join-path $OutputPath $ArchiveRoot) $Destination
Get-Item $Destination
}
} else {
Get-Item (Join-Path $OutputPath $ArchiveRoot)
}
}
$Archive.Dispose()
}
}