Powershell Zip Folder Contents
Solution 1
As per @mjolinor "H:\Stuff\", if you have .NET 4.5 installed you can run the following:
$src = "H:\Stuff\"
$dst = "H:\Stuff.zip"
[Reflection.Assembly]::LoadWithPartialName( "System.IO.Compression.FileSystem" )
[System.IO.Compression.ZipFile]::CreateFromDirectory($src, $dst)
Solution 2
If you use PSCX Module you will use the line code below to obtain what you need:
write-zip h:\Stuff\* myzipfile.zip
Solution 3
New solution available with WMF 5 (well not that new ^^)
Compress-Archive -Path H:\stuff\* -DestinationPath H:\stuff.zip -Force
user3402227
Updated on July 04, 2022Comments
-
user3402227 almost 2 years
I know a lot has been covered on zipping files using Powershell however I cannot find a method which does exactly what I need.
I want to be able to zip folders AND files into a .zip folder without having the parent folder inside the zip. So for example I have a folder named STUFF which contains files/folders, I want to zip this into a folder called STUFF.zip. This folders structure would then be STUFF.zip>files/folders NOT STUFF.zip>STUFF>files/folders as I currently get using this code...
function CountZipItems( [__ComObject] $zipFile) { If ($zipFile -eq $null) { Throw "Value cannot be null: zipFile" } Write-Host ("Counting items in zip file (" + $zipFile.Self.Path + ")...") [int] $count = CountZipItemsRecursive($zipFile) Write-Host ($count.ToString() + " items in zip file (" ` + $zipFile.Self.Path + ").") return $count } function CountZipItemsRecursive( [__ComObject] $parent) { If ($parent -eq $null) { Throw "Value cannot be null: parent" } [int] $count = 0 $parent.Items() | ForEach-Object { $count += 1 If ($_.IsFolder -eq $true) { $count += CountZipItemsRecursive($_.GetFolder) } } return $count } function IsFileLocked( [string] $path) { If ([string]::IsNullOrEmpty($path) -eq $true) { Throw "The path must be specified." } [bool] $fileExists = Test-Path $path If ($fileExists -eq $false) { Throw "File does not exist (" + $path + ")" } [bool] $isFileLocked = $true $file = $null Try { $file = [IO.File]::Open( $path, [IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::None) $isFileLocked = $false } Catch [IO.IOException] { If ($_.Exception.Message.EndsWith( "it is being used by another process.") -eq $false) { Throw $_.Exception } } Finally { If ($file -ne $null) { $file.Close() } } return $isFileLocked } function GetWaitInterval( [int] $waitTime) { If ($waitTime -lt 1000) { return 100 } ElseIf ($waitTime -lt 5000) { return 1000 } Else { return 5000 } } function WaitForZipOperationToFinish( [__ComObject] $zipFile, [int] $expectedNumberOfItemsInZipFile) { If ($zipFile -eq $null) { Throw "Value cannot be null: zipFile" } ElseIf ($expectedNumberOfItemsInZipFile -lt 1) { Throw "The expected number of items in the zip file must be specified." } Write-Host -NoNewLine "Waiting for zip operation to finish..." Start-Sleep -Milliseconds 1000 # ensure zip operation had time to start [int] $waitTime = 0 [int] $maxWaitTime = 60 * 1000 # [milliseconds] while($waitTime -lt $maxWaitTime) { [int] $waitInterval = GetWaitInterval($waitTime) Write-Host -NoNewLine "." Start-Sleep -Milliseconds $waitInterval $waitTime += $waitInterval Write-Debug ("Wait time: " + $waitTime / 1000 + " seconds") [bool] $isFileLocked = IsFileLocked($zipFile.Self.Path) If ($isFileLocked -eq $true) { Write-Debug "Zip file is locked by another process." Continue } Else { Break } } Write-Host If ($waitTime -ge $maxWaitTime) { Throw "Timeout exceeded waiting for zip operation" } [int] $count = CountZipItems($zipFile) If ($count -eq $expectedNumberOfItemsInZipFile) { Write-Debug "The zip operation completed succesfully." } ElseIf ($count -eq 0) { Throw ("Zip file is empty. This can occur if the operation is" ` + " cancelled by the user.") } ElseIf ($count -gt $expectedCount) { Throw "Zip file contains more than the expected number of items." } } function ZipFolder( [IO.DirectoryInfo] $directory) { If ($directory -eq $null) { Throw "Value cannot be null: directory" } Write-Host ("Creating zip file for folder (" + $directory.FullName + ")...") [IO.DirectoryInfo] $parentDir = $directory.Parent [string] $zipFileName If ($parentDir.FullName.EndsWith("\") -eq $true) { # e.g. $parentDir = "C:\" $zipFileName = $parentDir.FullName + $directory.Name + ".zip" } Else { $zipFileName = $parentDir.FullName + "\" + $directory.Name + ".zip" #$zipFileName = $directory.Name + ".zip" #$zipFileName = $parentDir.FullName + ".zip" } If (Test-Path $zipFileName) { Throw "Zip file already exists ($zipFileName)." } Set-Content $zipFileName ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) $shellApp = New-Object -ComObject Shell.Application $zipFile = $shellApp.NameSpace($zipFileName) If ($zipFile -eq $null) { Throw "Failed to get zip file object." } [int] $expectedCount = (Get-ChildItem $directory -Force -Recurse).Count $expectedCount += 1 # account for the top-level folder $zipFile.CopyHere($directory.FullName) #Get-ChildItem $directory | foreach {$zipFile.CopyHere($_.fullname)} # wait for CopyHere operation to complete WaitForZipOperationToFinish $zipFile $expectedCount Write-Host -Fore Green ("Successfully created zip file for folder (" ` + $directory.FullName + ").") }
Usage
Remove-Item "H:\STUFF.zip" [IO.DirectoryInfo] $directory = Get-Item "H:\STUFF" ZipFolder $directory
Complete credit goes here for this code. I really appreciate any help I get, this capability is crucial to my project! Unfortunately I cannot use the Community Extension module as other PC's this will be run on does not have this module installed.
Thanks!