Bulk ZIP Extraction with PowerShell: My Go-To Script (No Frills)
Not gonna lie, I used to avoid bulk ZIP extractions like the plague. Back in 2020, I tried unzipping 80 log bundles manually on a client’s Windows Server 2016 box. Explorer froze halfway through, and I ended up remoting in with Task Manager just to kill the session. Lesson learned.
These days, I just use PowerShell. It’s fast, predictable, and doesn’t care if you’re dealing with 5 files or 500.
Why I Use This Setup
I run Hyper-V on a ThinkPad with 32GB RAM, mostly testing scripts on Windows 11 and Server 2019 VMs. I get ZIPs from vendors, backups, and internal tools—some nested, some flat. I needed something that:
- Doesn’t assume hardcoded paths
- Can be handed off to junior admins
- Logs failures without crashing
- Doesn’t require installing third-party tools unless absolutely necessary
The Script I Actually Use
Here’s the base loop. I keep this saved as ExtractZips.ps1 and tweak paths as needed:
$Source = "D:\IncomingZips"
$Destination = "D:\Extracted"
Get-ChildItem -Path $Source -Filter *.zip | ForEach-Object {
$ZipFile = $_.FullName
$DestPath = Join-Path $Destination $_.BaseName
Expand-Archive -Path $ZipFile -DestinationPath $DestPath -Force
}
Each ZIP gets its own folder. I used to extract everything into one folder, but that got messy fast—conflicts, overwrites, missing DLLs. Never again.
When I Need It to Be Click-Friendly
If I’m handing this off to someone who’s not comfortable editing paths, I add a folder picker:
Add-Type -AssemblyName System.Windows.Forms
function Select-Folder($Message) {
$dialog = New-Object System.Windows.Forms.FolderBrowserDialog
$dialog.Description = $Message
if ($dialog.ShowDialog() -eq 'OK') {
return $dialog.SelectedPath
} else {
Write-Output "No folder selected. Exiting script."
exit
}
}
$Source = Select-Folder "Select ZIP folder"
$Destination = Select-Folder "Select destination folder"
I’ve used this version on a couple of client laptops—non-admin users just double-click and follow the prompts.
Logging Success and Failures
This part saved me last month when a corrupted ZIP silently failed. I didn’t even notice until I checked the log:
$LogFile = "D:\Logs\ExtractLog.txt"
Get-ChildItem -Path $Source -Filter *.zip | ForEach-Object {
try {
$ZipFile = $_.FullName
$DestPath = Join-Path $Destination $_.BaseName
Expand-Archive -Path $ZipFile -DestinationPath $DestPath -Force
Add-Content -Path $LogFile -Value "SUCCESS: $ZipFile → $DestPath"
} catch {
Add-Content -Path $LogFile -Value "ERROR: $ZipFile → $_"
}
}
I don’t always include logging, but when I do, it’s usually because I’m running this on a schedule.
Scheduling It (Set and Forget)
If you’re dealing with recurring ZIPs—like nightly backups or vendor drops—just schedule the script:
- Save as
ExtractZips.ps1 - Use Task Scheduler
- Trigger: Daily or at logon
- Action:
powershell.exe -File "D:\Scripts\ExtractZips.ps1"
I’ve got this running on two client boxes. No GUI, no prompts—just extracts and logs.
A Few Quirks
- Password-protected ZIPs: PowerShell doesn’t support them. I use 7-Zip CLI:
& "C:\Program Files\7-Zip\7z.exe" x "secure.zip" -pYourPassword -oExtracted -y
- Nested folders: Use
-RecursewithGet-ChildItemif your ZIPs are buried. - Overwrite issues: Always use
-Force, or wrap intry/catch. - Compression: You can reverse the process with
Compress-Archive.
Final Thought
This isn’t a fancy setup. It’s just what works. I’ve used it on everything from dev VMs to production boxes. If you’ve got a better way—or hit a weird edge case—drop a note. I’m always tweaking this.
Ever tried extracting ZIPs from a network share with flaky permissions? That’s a whole other story…
