Last active
January 8, 2026 12:17
-
-
Save SQLDBAWithABeard/fc2c5bf1e0c2ba6a89e88d234e1a79c0 to your computer and use it in GitHub Desktop.
UnZipJustSubDir
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function Expand-ZipSubdirectory { | |
| <# | |
| .SYNOPSIS | |
| Extracts only a specific subdirectory from a ZIP archive. | |
| .DESCRIPTION | |
| Expand-ZipSubdirectory allows selective extraction of a single subdirectory | |
| from a ZIP file. Unlike Expand-Archive, which extracts the entire archive, | |
| this function filters ZIP entries by path and extracts only the matching | |
| subtree. | |
| The function validates: | |
| - The ZIP file exists and has a .zip extension | |
| - The destination directory exists or can be created | |
| - The subdirectory parameter is not empty | |
| ZIP archives always use forward slashes internally. The function normalizes | |
| the provided subdirectory path automatically. | |
| .PARAMETER ZipPath | |
| The full path to the .zip file. Must exist and must have a .zip extension. | |
| .PARAMETER Subdirectory | |
| The internal ZIP subdirectory to extract. This should be the folder path | |
| inside the ZIP (e.g., "module/MicrosoftFabricMgmt"). | |
| .PARAMETER Destination | |
| The directory where the extracted files will be placed. If it does not exist, | |
| the function attempts to create it. | |
| .PARAMETER Force | |
| If specified, existing files in the destination will be overwritten. | |
| .EXAMPLE | |
| Expand-ZipSubdirectory -ZipPath "C:\temp\package.zip" ` | |
| -Subdirectory "module/MicrosoftFabricMgmt" ` | |
| -Destination "C:\temp\extract" | |
| Extracts only the MicrosoftFabricMgmt subdirectory from the ZIP. | |
| .EXAMPLE | |
| Expand-ZipSubdirectory -ZipPath ".\build.zip" ` | |
| -Subdirectory "output/bin" ` | |
| -Destination ".\bin" ` | |
| -Force | |
| Extracts the "output/bin" folder and overwrites existing files. | |
| .NOTES | |
| This function uses System.IO.Compression.ZipFile from .NET and does not rely | |
| on Expand-Archive. It supports nested directories and preserves structure. | |
| #> | |
| [CmdletBinding()] | |
| param( | |
| [Parameter(Mandatory)] | |
| [ValidateNotNullOrEmpty()] | |
| [ValidateScript({ | |
| if (-not (Test-Path $_)) { | |
| throw "ZipPath '$_' does not exist." | |
| } | |
| if (-not ($_ -match '\.zip$')) { | |
| throw "ZipPath '$_' is not a .zip file." | |
| } | |
| $true | |
| })] | |
| [string]$ZipPath, | |
| [Parameter(Mandatory)] | |
| [ValidateNotNullOrEmpty()] | |
| [string]$Subdirectory, | |
| [Parameter(Mandatory)] | |
| [ValidateNotNullOrEmpty()] | |
| [ValidateScript({ | |
| if (-not (Test-Path $_)) { | |
| try { | |
| New-Item -ItemType Directory -Path $_ -ErrorAction Stop | Out-Null | |
| } | |
| catch { | |
| throw "Destination '$_' does not exist and could not be created." | |
| } | |
| } | |
| $true | |
| })] | |
| [string]$Destination, | |
| [switch]$Force | |
| ) | |
| # Normalize ZIP internal path format | |
| $normalized = $Subdirectory.TrimStart('/','\') -replace '\\','/' | |
| if (-not $normalized.EndsWith('/')) { | |
| $normalized += '/' | |
| } | |
| Add-Type -AssemblyName System.IO.Compression.FileSystem | |
| $zip = [System.IO.Compression.ZipFile]::OpenRead($ZipPath) | |
| try { | |
| $matched = $false | |
| foreach ($entry in $zip.Entries) { | |
| if ($entry.FullName.StartsWith($normalized, [StringComparison]::OrdinalIgnoreCase)) { | |
| $matched = $true | |
| $relative = $entry.FullName.Substring($normalized.Length) | |
| if (-not $relative) { continue } | |
| $target = Join-Path $Destination $relative | |
| $targetDir = Split-Path $target | |
| if (-not (Test-Path $targetDir)) { | |
| New-Item -ItemType Directory -Path $targetDir | Out-Null | |
| } | |
| if ($entry.Name) { | |
| [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $target, $Force.IsPresent) | |
| } | |
| } | |
| } | |
| if (-not $matched) { | |
| throw "Subdirectory '$Subdirectory' was not found inside the ZIP." | |
| } | |
| } | |
| finally { | |
| $zip.Dispose() | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| I am big! It's the pictures that got small. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment