Modern hard drives are divided into blocks. These blocks can be of various sizes. 512K, 1024K. The issue that can develop is that once a block contains the data of a file, the unused portion of that block cannot store an other data. So for example, if you save a 768K file onto a hard drive containing 512K blocks, your file will consume 1024K. 256K will be unusable space. This script will show you how much space is being wasted.
This script is a quick demo based on a question that popped up in class. Utilizing FRSM quotas, I set a folder with a hard quota of 6KB. I then copied a file of 2KB into the folder. When I copied the same file in again, Windows stated that I exceeded my quota. Well, logically 2 KB + 2 KB = 4 KB. My quota was 6 KB.
Upon further analysis, we discovered that the file size was actually a few kilobytes larger than 2.5 K. That means that on my hard drive with block sizes of 512K, we were using 6 blocks or 3 KB. The second file fit the limit and we received an error.
This script is designed to be dot sourced into the shell environment of PowerShell.
<#
.SYNOPSIS
Returns the amount of space that is unused in the files blocks.
.DESCRIPTION
Returns the amount of space that is not available to be
used on the hard drive due to the blocki size on the hard drives.
If a file only uses part of a block, the rest of the block cannot
be used for another file.
.PARAMETER Recurse
Performs a recursive search using the current location
in the file system as the root.
.EXAMPLE
Get-WastedSpace -Recurse
Returns the wasted space on the hard drive based on the
current location in the file system as the root of the search.
#>
function Get-WastedDriveSpace
{
Param
(
[Switch]$Recurse
)
# Get the Disk Partition information
$DiskPartition = Get-WmiObject Win32_DiskPArtition |
Select-Object -Property BlockSize
# Get the logical disk information
$LogicalDisk = Get-WmiObject Win32_LogicalDIsk |
Select-object -Property Name
If ($Recurse)
{
$Files = Get-ChildItem -Recurse |
Select-Object -Property length, PSDrive
}
Else
{
$Files = Get-ChildItem |
Select-Object -Property length, PSDrive
}
$DriveObj = @()
$Counter = 0
forEach ($Disk in $LogicalDisk)
{
$DriveInfo = New-Object PSObject
$DriveInfo | Add-Member NoteProperty -Name Name -Value ($Disk.Name).Replace(":","")
$DriveInfo | Add-Member NoteProperty -Name BlockSize $DiskPartition[$Counter].BlockSize
$DriveInfo | Add-Member NoteProperty -Name TotalFileSize -Value 0
$DriveInfo | Add-Member NoteProperty -Name TotalBlocksUsed -Value 0
$DriveInfo | Add-Member NoteProperty -Name SizeOfBlocks -value 0
$DriveInfo | Add-Member NoteProperty -Name WastedSpaceMB -Value 0
$DriveObj += $DriveInfo
$Counter++
} # End: for Each ($File in $Files)
ForEach ($File in $Files)
{
ForEach ($Drive in $DriveObj)
{
If ($File.PSDrive -like $Drive.Name)
{
$Drive.TotalFileSize += $File.Length
$Drive.TotalBlocksUsed += [int]($File.Length/$Drive.BlockSize)
$Drive.SizeOfBlocks += ($Drive.TotalBlocksUsed * $Drive.BlockSize)
}
} # End: ForEach ($Drive in $DriveObj)
} # End: ForEach ($File in $Files)
# Calculate the Wasted Space.
ForEach ($Drive in $DriveObj)
{
$Drive.WastedSpaceMB = ($Drive.SizeOfBlocks - $Drive.TotalFileSize) / 1mb
} # End: ForEach ($Drive in $DriveObj)
# Write the object to the pipline
Write-Output $DriveObj
} # End: Get-WastedDriveSpace
Comments