/commands/powershell/compress-archive-zip-folder
Compress-Archive: zip a folder in PowerShell (and unzip it with Expand-Archive)
- tool
- PowerShell
- versions
- Windows PowerShell 5.1 (Microsoft.PowerShell.Archive 1.0.1.0), PowerShell 7.x
- os
- windows, linux, macos
Compress-Archive -Path C:\project -DestinationPath C:\project.zip zips a folder in PowerShell, and Expand-Archive C:\project.zip -DestinationPath C:\out unzips it. Both cmdlets come with Windows PowerShell 5.1 and PowerShell 7 in the Microsoft.PowerShell.Archive module, so nothing needs to be installed.
Compress-Archive -Path .\project -DestinationPath .\project.zip
Compress-Archive -Path .\project\* -DestinationPath .\contents.zip # without the top folder
Compress-Archive -Path .\project -DestinationPath .\project.zip -Force # overwrite
Expand-Archive -Path .\project.zip -DestinationPath .\outWith or without the top folder
The block creates a small folder, zips it both ways and lists the entry names stored in each archive:
New-Item -ItemType Directory -Force project\src | Out-Null
'a' | Set-Content project\src\a.txt
'r' | Set-Content project\README.md
Compress-Archive -Path project -DestinationPath with-folder.zip
Compress-Archive -Path project\* -DestinationPath contents.zip
Add-Type -AssemblyName System.IO.Compression.FileSystem
foreach ($z in 'with-folder.zip', 'contents.zip') {
$a = [IO.Compression.ZipFile]::OpenRead("$PWD\$z")
"${z}: " + (($a.Entries.FullName | Sort-Object) -join ' | ')
$a.Dispose()
}Output
with-folder.zip: project\README.md | project\src\a.txt contents.zip: README.md | src\a.txt
Passing the folder keeps project\ as the first path component; project\* stores what is inside it. project\*.* would take only the files at the top level and skip subfolders.
Windows PowerShell 5.1 (module version 1.0.1.0) writes the entry names with backslashes, as the output shows. Windows tools handle them, but some unzip programs on Linux and macOS treat the backslash as part of the file name and extract project\src\a.txt as one flat file. If the archive is for another platform, create it with tar.exe, shown below.
Parameters
| Parameter | What it does |
|---|---|
| -Path | Files or folders to add; wildcards allowed; several paths separated by commas |
| -LiteralPath | Same, but [ ] and * are taken literally |
| -DestinationPath | The .zip to create; the .zip extension is added if missing |
| -Force | Overwrite an existing archive |
| -Update | Add new files and replace older copies inside an existing archive |
| -CompressionLevel | Optimal (default), Fastest or NoCompression |
| -PassThru | Return the archive as a FileInfo object (PowerShell 6.0 and later) |
Errors you will meet
New-Item -ItemType Directory -Force project | Out-Null; 'x' | Set-Content project\f.txt
Compress-Archive -Path project -DestinationPath p.zip
try { Compress-Archive -Path project -DestinationPath p.zip -ErrorAction Stop } catch { $_.FullyQualifiedErrorId }
try { Compress-Archive -Path project -DestinationPath p.7z -ErrorAction Stop } catch { $_.Exception.Message }
Expand-Archive p.zip -DestinationPath out
try { Expand-Archive p.zip -DestinationPath out -ErrorAction Stop } catch { $_.FullyQualifiedErrorId }
Expand-Archive p.zip -DestinationPath out -Force; 'expanded again with -Force'Output
ArchiveFileExists,Compress-Archive .7z is not a supported archive file format. .zip is the only supported archive file format. ExpandArchiveFileExists,ExpandArchiveHelper expanded again with -Force
The full message for an existing archive is The archive file ... already exists. Use the -Update parameter to update the existing archive file or use the -Force parameter to overwrite the existing archive file. Expand-Archive refuses to overwrite existing files in the same way until you add -Force.
Limits
- Each file must be smaller than 2 GB: the cmdlet uses the
System.IO.Compression.ZipArchiveAPI, which has that limit. - Hidden files and folders are skipped.
Get-ChildItem -Recurse | Compress-Archiveadds every file twice (once inside its folder, once at the root); pass the folder to-Pathinstead.
tar.exe as an alternative
Windows 10 and 11 include bsdtar as tar.exe. With -a it picks the format from the extension, so it can write a zip with forward-slash entry names and hidden files:
mkdir project\src
>project\src\a.txt echo a
tar -a -c -f project.zip project
tar -t -f project.zipOutput
project/ project/src/ project/src/a.txt
Check the result with tar -t -f FILE.zip or by expanding it into an empty folder before you send it.
FAQ
How do I zip the contents of a folder without the folder itself?
Add a wildcard to the path: Compress-Archive -Path C:\project\* -DestinationPath project.zip. Without the wildcard the archive contains a top-level project folder.
Why are hidden files missing from my zip?
Compress-Archive skips hidden files and folders (on Linux and macOS, names starting with a dot). Use tar.exe or the System.IO.Compression.ZipFile .NET API when they must be included.
Can Compress-Archive create a .7z or .tar.gz file?
No. It writes only .zip and fails with '.7z is not a supported archive file format. .zip is the only supported archive file format.' For .tar.gz use tar -czf, which ships with Windows 10 and 11.
Sources
- learn.microsoft.comlearn.microsoft.com/en-us/powershell/module/microsoft.powershell.archive/compress-archive?view=powershell-5.1
- learn.microsoft.comlearn.microsoft.com/en-us/powershell/module/microsoft.powershell.archive/compress-archive?view=powershell-7.5
- learn.microsoft.comlearn.microsoft.com/en-us/powershell/module/microsoft.powershell.archive/expand-archive?view=powershell-5.1