Last active
March 18, 2021 14:42
-
-
Save tunaworks/a1e303a060c83b7884cd72fbed0ec163 to your computer and use it in GitHub Desktop.
Gets the size and path of all subdirectories below a specied size, and option to delete them.
This file contains 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
#Code progress: | |
# finds actual size of a folder | |
# finds all directories & sub-directories | |
# filters folder < minsize | |
# format size to corresponding denom (B,KB..etc) | |
# store each matched result as a custom object with multiple properties | |
# store each match in an array (Results) | |
# print Result array as formatted table on command line. | |
# to do: | |
# remove the actual filtered folders (*do this in the ForEach loop, not the array? | |
#or give confirmation dialog option idk) | |
# Parent Directory to find folders | |
$dirpath = "H:\Tutorial M3\Rock Band" | |
$logpath = "$PSScriptRoot\Logs\" | |
$logpath = -join($logpath, ($dirpath|split-path -leaf), ".txt") | |
# Maximum size of each folder (empty or non-empty) | |
# e.g Find/Delete all folders smaller than 5MB | |
$foldermaxsize = 5 # <- max size of each folder (e.g. 10 * 1MB = 10MB, 10 * 1KB = 10KB, etc) | |
$sizeunit = 1MB # <- size denominator (e.g. 1KB, 1MB, 1GB, etc) | |
$foldermaxsize = $foldermaxsize * $sizeunit | |
$Final = new-object PSObject -Property @{"Length"= 0; "Size"=0} | |
# PRINT FORMATTING (takes in bytes, formats it with appropriate size denom) | |
Function Format-Size{ | |
[cmdletbinding()] | |
Param ( | |
[Parameter(Mandatory=$true, Position=0, ValueFromPipeline = $true)] | |
$Bytes | |
) | |
switch -Regex ([math]::truncate([math]::log($bytes,1024))) { | |
'^0' {"$bytes Bytes"} | |
'^1' {"{0:n2} KB" -f ($bytes / 1KB)} | |
'^2' {"{0:n2} MB" -f ($bytes / 1MB)} | |
'^3' {"{0:n2} GB" -f ($bytes / 1GB)} | |
'^4' {"{0:n2} TB" -f ($bytes / 1TB)} | |
Default {"{0:n2} PB" -f ($bytes / 1PB)} | |
} | |
} | |
$sizestring = Format-Size $foldermaxsize | |
# returns size of single folder by summing all items (recursive) inside | |
Function Get-FolderSize { | |
# allows cmd options | |
[cmdletbinding()] | |
Param ( | |
[Parameter(Mandatory=$true, Position=0, ValueFromPipeline = $true)] | |
$folderpath | |
) | |
$size = 0 | |
Write-Information $folderpath | |
# calculate folder size and recurse as needed | |
Foreach ($file in $(gci -LiteralPath $folderpath -recurse -force)){ | |
If (-not ($file.psiscontainer)) { | |
$size += $file.length | |
} | |
} | |
# return the value and go back to caller | |
return $size | |
} | |
# filter = returns boolean TRUE if foldersize (passed from pipeline) is lt $foldermaxsize | |
Function Filter-FolderSize{ | |
[cmdletbinding()] | |
Param ( | |
[Parameter(Mandatory=$true, Position=0, ValueFromPipeline = $true)] | |
$foldersize | |
) | |
if ($foldersize -lt $foldermaxsize){ | |
return $true | |
}else{ | |
return $false | |
} | |
} | |
# Array containing filepaths of each directory (recursive) found within $dirpath | |
# gci = GetChildItem | |
$Folders = @(gci -LiteralPath $dirpath -Recurse | ?{ $_.PSIsContainer } | Select-Object -ExpandProperty FullName) | |
# Check for null results from cgi function | |
if ($Folders.length -eq 0) { | |
write-host " no folders." | |
} else { | |
# $Results = array of PSobjects containing (Size,folderpath) | |
$Result = @() | |
# $folder = full path of current folder | |
ForEach ($folder in $Folders){ | |
# returns int size of Folder (by recursively summing all child filesize) | |
$curfoldersize = Get-FolderSize $folder | |
# returns boolean T/F | |
$curfilter = Filter-FolderSize $curfoldersize | |
# excludes parent dir from final pathname | |
$folder = $folder.Replace(($dirpath+"\"), "") | |
# add to $Results array | |
if ($curfilter){ | |
$obj = new-object PSObject -Property @{"Size"= $curfoldersize; "Path"=$folder} | |
$Result += $obj | |
$Final.Size += $curfoldersize | |
$Final.Length +=1 | |
} | |
} | |
# Result_Table formatted output | |
$Result_Table = $Result | Select-Object Size,Path | Format-Table ` | |
-Property ` | |
(@{Name=("Size"+ "(" + (Format-Size $sizeunit) + ")" );Expression={Format-Size($_.Size)};align='right'},` | |
@{Name='Path';Expression={$_.Path};align='left'}) ` | |
Write-Output $Result_Table | |
#Write-Output $Result.Path $Final.Length (Format-Size $Final.size) | |
$title = 'Delete ' + $Final.Length + ' folders? (' + (Format-Size $Final.size) + ')' | |
$question = 'Y/N?' | |
$yes = New-Object System.Management.Automation.Host.ChoiceDescription '&Yes','Deletes selected | |
folders' | |
$no = New-Object System.Management.Automation.Host.ChoiceDescription '&No','Leaves folders untouched' | |
$options = [System.Management.Automation.Host.ChoiceDescription[]] ($Yes,$No) | |
$choice = $Host.UI.PromptForChoice($title,$question,$options,1) | |
if ($choice -eq 0) { | |
Write-Host 'confirmed' | |
Start-Transcript $logpath | |
ForEach($member in $Result){ | |
$path = Join-Path -Path $dirpath -ChildPath $member.Path | |
$path = [wildcardpattern]::Escape($path) | |
Write-Output -join @($path,"(",$member.Size,")") | |
Remove-Item -Confirm:$false -Recurse $path | |
} | |
Stop-Transcript | |
} else { | |
Write-Host 'cancelled' | |
} | |
if ($Host.Name -eq "ConsoleHost") | |
{ | |
Write-Host "Press any key to continue..." | |
$Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp") > $null | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment