Skip to content

/commands/powershell/compress-archive-zip-folder

Compress-Archive: zip a folder in PowerShell (and unzip it with Expand-Archive)

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
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.

powershell
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 .\out

With or without the top folder

The block creates a small folder, zips it both ways and lists the entry names stored in each archive:

powershell
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

ParameterWhat it does
-PathFiles or folders to add; wildcards allowed; several paths separated by commas
-LiteralPathSame, but [ ] and * are taken literally
-DestinationPathThe .zip to create; the .zip extension is added if missing
-ForceOverwrite an existing archive
-UpdateAdd new files and replace older copies inside an existing archive
-CompressionLevelOptimal (default), Fastest or NoCompression
-PassThruReturn the archive as a FileInfo object (PowerShell 6.0 and later)

Errors you will meet

powershell
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.ZipArchive API, which has that limit.
  • Hidden files and folders are skipped.
  • Get-ChildItem -Recurse | Compress-Archive adds every file twice (once inside its folder, once at the root); pass the folder to -Path instead.

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:

cmd
mkdir project\src
>project\src\a.txt echo a
tar -a -c -f project.zip project
tar -t -f project.zip

Output

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