Skip to content

Instantly share code, notes, and snippets.

@lirrensi
Created February 13, 2026 03:20
Show Gist options
  • Select an option

  • Save lirrensi/4eda18d6fcc0ea6b491f7bdc829722d4 to your computer and use it in GitHub Desktop.

Select an option

Save lirrensi/4eda18d6fcc0ea6b491f7bdc829722d4 to your computer and use it in GitHub Desktop.
PWSH script to shink overgrown WSL and reclaim disk space. Finds all containers and removes free space made by autogrow. Warning: may kill your wsl! Close first pls.
# WSL VHDX Shrink Script
# This fancy lil script will save ur precious space cause microslop geniuses forgot that auto-growing disks need periodic compaction.
$ErrorActionPreference = "Stop"
# Check if running as admin
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) {
Write-Host "`n❌ Not running as Administrator. Come on, really?" -ForegroundColor Red
Write-Host "Right-click and 'Run as Administrator' like a normal person.`n" -ForegroundColor Yellow
exit 1
}
# Find all VHDX files in AppData
Write-Host "`nπŸ” Searching for VHDX files..." -ForegroundColor Cyan
Write-Host "This might take a moment because AppData is a dumpster fire...`n" -ForegroundColor DarkGray
# Scan entire LOCALAPPDATA for VHDX files
$vhdxFiles = Get-ChildItem -Path $env:LOCALAPPDATA -Filter "*.vhdx" -Recurse -ErrorAction SilentlyContinue -Force
if ($vhdxFiles.Count -eq 0) {
Write-Host "❌ No VHDX files found. Do you even have WSL installed?" -ForegroundColor Red
exit 1
}
Write-Host "βœ… Found $($vhdxFiles.Count) VHDX file(s)`n" -ForegroundColor Green
# Build selection list with sizes
$vhdxList = @()
foreach ($file in $vhdxFiles) {
$sizeGB = [math]::Round($file.Length / 1GB, 2)
$vhdxList += @{
Path = $file.FullName
Name = $file.Name
Directory = $file.DirectoryName
SizeGB = $sizeGB
}
}
# Add "Compact All" option
$vhdxList += @{
Path = "ALL"
Name = "Compact All VHDX Files"
Directory = ""
SizeGB = $vhdxList.Count
}
# Arrow key selection menu
$currentIndex = 0
$maxIndex = $vhdxList.Count - 1
function Show-Menu {
param($index)
Clear-Host
Write-Host "`nπŸ“‹ Select a VHDX file to shrink (Use ↑↓ arrows, Enter to select):" -ForegroundColor Yellow
Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -ForegroundColor DarkGray
for ($i = 0; $i -lt $vhdxList.Count; $i++) {
$vhdx = $vhdxList[$i]
$prefix = if ($i -eq $index) { "β–Ά " } else { " " }
$color = if ($i -eq $index) { "Green" } else { "White" }
if ($vhdx.Path -eq "ALL") {
Write-Host "$prefixπŸ’₯ Compact All $($vhdx.SizeGB) VHDX Files" -ForegroundColor $color
} else {
Write-Host "$prefixπŸ’Ύ $($vhdx.Name) - $($vhdx.SizeGB) GB" -ForegroundColor $color
if ($i -eq $index) {
Write-Host " πŸ“ $($vhdx.Directory)" -ForegroundColor DarkGray
}
}
}
Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -ForegroundColor DarkGray
}
# Menu loop
while ($true) {
Show-Menu -index $currentIndex
$key = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
switch ($key.VirtualKeyCode) {
38 { # Up arrow
if ($currentIndex -gt 0) { $currentIndex-- }
}
40 { # Down arrow
if ($currentIndex -lt $maxIndex) { $currentIndex++ }
}
13 { # Enter
$selectedVHDX = $vhdxList[$currentIndex]
break
}
}
if ($key.VirtualKeyCode -eq 13) { break }
}
Clear-Host
if ($selectedVHDX.Path -eq "ALL") {
Write-Host "`nπŸ’₯ Selected: Compact All VHDX Files" -ForegroundColor Green
Write-Host "πŸ“ Count: $($selectedVHDX.SizeGB) files" -ForegroundColor White
} else {
Write-Host "`nβœ… Selected: $($selectedVHDX.Name)" -ForegroundColor Green
Write-Host "πŸ“ Path: $($selectedVHDX.Path)" -ForegroundColor White
Write-Host "πŸ’Ύ Current size: $($selectedVHDX.SizeGB) GB`n" -ForegroundColor Yellow
}
# Step 1: Shutdown ALL WSL instances
Write-Host "⏹️ Shutting down all WSL instances..." -ForegroundColor Cyan
Write-Host "(If WSL is running, this will kill it. Save your work!)`n" -ForegroundColor Yellow
# Add confirmation prompt
Write-Host "❓ Are you sure you want to shut down all WSL instances?" -ForegroundColor Yellow
$confirmation = Read-Host "Type 'YES' to confirm, anything else to cancel"
if ($confirmation -ne "YES") {
Write-Host "❌ Operation cancelled by user." -ForegroundColor Red
exit 1
}
Start-Sleep -Seconds 2
try {
wsl --shutdown
Start-Sleep -Seconds 3
Write-Host "βœ… WSL shut down`n" -ForegroundColor Green
} catch {
Write-Host "⚠️ WSL shutdown failed, but we'll try anyway..." -ForegroundColor Yellow
}
# Step 2: Optimize/Shrink VHDX
if ($selectedVHDX.Path -eq "ALL") {
Write-Host "πŸ—œοΈ Compacting ALL VHDX files..." -ForegroundColor Cyan
Write-Host "This might take a while. Go touch grass or something.`n" -ForegroundColor DarkGray
# Compact all VHDX files
foreach ($vhdx in $vhdxList) {
if ($vhdx.Path -ne "ALL") {
Write-Host "Processing: $($vhdx.Name) - $($vhdx.SizeGB) GB" -ForegroundColor Yellow
$diskpartScript = @"
select vdisk file="$($vhdx.Path)"
attach vdisk readonly
compact vdisk
detach vdisk
exit
"@
$scriptPath = "$env:TEMP\diskpart_shrink_$(Get-Random).txt"
$diskpartScript | Out-File -FilePath $scriptPath -Encoding ASCII
try {
$result = diskpart /s $scriptPath 2>&1
# Check if diskpart actually succeeded
if ($LASTEXITCODE -eq 0) {
Write-Host "βœ… $($vhdx.Name) compacted successfully!" -ForegroundColor Green
} else {
Write-Host "❌ Failed to compact $($vhdx.Name)" -ForegroundColor Red
Write-Host "Output: $result" -ForegroundColor DarkGray
}
} catch {
Write-Host "❌ Something went wrong with $($vhdx.Name): $_" -ForegroundColor Red
} finally {
Remove-Item $scriptPath -ErrorAction SilentlyContinue
}
}
}
} else {
Write-Host "πŸ—œοΈ Shrinking VHDX..." -ForegroundColor Cyan
Write-Host "This might take a minute. Go touch grass or something.`n" -ForegroundColor DarkGray
$vhdxPath = $selectedVHDX.Path
$diskpartScript = @"
select vdisk file="$vhdxPath"
attach vdisk readonly
compact vdisk
detach vdisk
exit
"@
$scriptPath = "$env:TEMP\diskpart_shrink_$(Get-Random).txt"
$diskpartScript | Out-File -FilePath $scriptPath -Encoding ASCII
try {
$result = diskpart /s $scriptPath 2>&1
# Check if diskpart actually succeeded
if ($LASTEXITCODE -eq 0) {
Write-Host "βœ… VHDX shrunk successfully!`n" -ForegroundColor Green
} else {
Write-Host "❌ Diskpart failed with exit code: $LASTEXITCODE" -ForegroundColor Red
Write-Host "Output: $result" -ForegroundColor DarkGray
throw "Diskpart operation failed"
}
} catch {
Write-Host "❌ Something went wrong. The disk gods are angry." -ForegroundColor Red
Write-Host "Error: $_" -ForegroundColor Red
exit 1
} finally {
Remove-Item $scriptPath -ErrorAction SilentlyContinue
}
}
# Show results
if ($selectedVHDX.Path -ne "ALL") {
$sizeAfter = [math]::Round((Get-Item $vhdxPath).Length / 1GB, 2)
$saved = [math]::Round($selectedVHDX.SizeGB - $sizeAfter, 2)
Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -ForegroundColor Green
Write-Host "πŸ“Š RESULTS:" -ForegroundColor Cyan
Write-Host " Before: $($selectedVHDX.SizeGB) GB" -ForegroundColor White
Write-Host " After: $sizeAfter GB" -ForegroundColor White
if ($saved -gt 0) {
Write-Host " Saved: $saved GB πŸŽ‰" -ForegroundColor Green
} else {
Write-Host " Saved: $saved GB (lol nothing)" -ForegroundColor Yellow
}
Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`n" -ForegroundColor Green
} else {
Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -ForegroundColor Green
Write-Host "πŸ“Š RESULTS:" -ForegroundColor Cyan
Write-Host " Processed $($selectedVHDX.SizeGB) VHDX files" -ForegroundColor White
Write-Host " All files have been compacted" -ForegroundColor Green
Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`n" -ForegroundColor Green
}
Write-Host "✨ All done! Your disk is slightly less full.`n" -ForegroundColor Green
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment