How to Get the Cluster Size of a Volume in Batch Script
The Cluster Size (also called Allocation Unit Size) is the smallest block of space the file system uses to store data. If your cluster size is 4 KB and you save a 1-byte text file, it still consumes 4 KB of disk space. Understanding this is critical for optimizing storage: large clusters are faster for big files (like video editing or databases) but waste space with small files; small clusters are space-efficient but slower for bulk I/O. A Batch script can query the cluster size of any volume, providing the intelligence needed for storage tuning, format planning, and performance optimization.
This guide will explain how to query the allocation unit size.
Why Cluster Size Matters
| Cluster Size | Space Efficiency | I/O Performance | Best For |
|---|---|---|---|
| 512 bytes | Maximum (minimal waste) | Slowest (many small reads/writes) | Rarely used |
| 4 KB (4096) | Good, default for most NTFS | Good, balanced for mixed workloads | General purpose, OS drives, office work |
| 8 KB | Moderate | Better for medium files | File servers with mixed content |
| 16 KB | Lower | Good for large files | Media storage |
| 64 KB | Lowest (significant waste with small files) | Best for sequential I/O | SQL Server, Hyper-V, virtual disks |
The space waste problem:
Every file, no matter how small, occupies at least one cluster. With 64 KB clusters, a 1-byte file wastes 65,535 bytes. A folder with 10,000 small log files (each under 1 KB) would waste approximately 625 MB. Conversely, with 4 KB clusters, a 10 GB database file requires 2,621,440 allocation entries in the MFT, whereas 64 KB clusters need only 163,840 entries, reducing metadata overhead and improving sequential read/write speed.
Method 1: Check a Specific Drive
This method queries the cluster size of a specific volume and provides context about what the size means for different workloads.
Implementation
@echo off
setlocal
set "Drive=%~1"
if "%Drive%"=="" (
echo Usage: %~nx0 ^<drive_letter^>
echo.
echo Examples:
echo %~nx0 C
echo %~nx0 D
endlocal
exit /b 1
)
:: Normalize drive letter
set "DriveLetter=%Drive:~0,1%"
set "DriveColon=%DriveLetter%:"
if not exist %DriveColon%\ (
echo [ERROR] Drive %DriveColon% does not exist or is not accessible. >&2
endlocal
exit /b 1
)
echo [INFO] Cluster size for %DriveColon%
echo.
:: Use PowerShell for reliable, cross-filesystem cluster size retrieval
powershell -NoProfile -Command ^
"try {" ^
" $vol = Get-Volume -DriveLetter '%DriveLetter%' -ErrorAction Stop;" ^
" $wmiVol = Get-CimInstance Win32_Volume -Filter \"DriveLetter='%DriveColon%'\" -ErrorAction SilentlyContinue;" ^
" $clusterSize = if ($wmiVol) { $wmiVol.BlockSize } else { 'Unknown' };" ^
" Write-Host \" Drive: %DriveColon%\";" ^
" Write-Host \" File System: $($vol.FileSystemType)\";" ^
" Write-Host \" Cluster Size: $clusterSize bytes\";" ^
" if ($clusterSize -is [int] -or $clusterSize -is [long]) {" ^
" $clusterKB = $clusterSize / 1024;" ^
" Write-Host \" ($clusterKB KB)\"" ^
" };" ^
" Write-Host \" Label: $(if ($vol.FileSystemLabel) { $vol.FileSystemLabel } else { '(none)' })\";" ^
" Write-Host \" Total Size: $([math]::Round($vol.Size / 1GB, 1)) GB\";" ^
" Write-Host '';" ^
" if ($clusterSize -eq 4096) {" ^
" Write-Host ' [INFO] 4 KB - Standard default. Good for general-purpose workloads.'" ^
" } elseif ($clusterSize -eq 65536) {" ^
" Write-Host ' [INFO] 64 KB - Optimized for large files and databases.';" ^
" Write-Host ' [INFO] May waste space with many small files.'" ^
" } elseif ($clusterSize -lt 4096) {" ^
" Write-Host ' [INFO] Below standard (512 or 2048 bytes). Uncommon configuration.'" ^
" } elseif ($clusterSize -gt 4096 -and $clusterSize -lt 65536) {" ^
" Write-Host \" [INFO] Non-default cluster size. May have been set intentionally for specific workloads.\"" ^
" }" ^
"} catch {" ^
" Write-Error $_.Exception.Message;" ^
" exit 1" ^
"}"
endlocal
exit /b 0
Sample output:
[INFO] Cluster size for C:
Drive: C:
File System: NTFS
Cluster Size: 4096 bytes
Label: (none)
Total Size: 440.7 GB
[INFO] 4 KB - Standard default. Good for general-purpose workloads.
Why Win32_Volume.BlockSize instead of fsutil:
fsutil fsinfo ntfsinfoonly works on NTFS volumes. On FAT32 or exFAT drives, it fails with an error.fsutilrequires administrator privileges for most queries.Win32_Volume.BlockSizereturns the allocation unit size for any file system type (NTFS, FAT32, exFAT, ReFS) and works consistently across Windows versions.- On some systems,
Get-Volumealone does not expose the cluster size, which is whyWin32_Volumefrom WMI is used as the data source.
Method 2: All-Drive Cluster Size Inventory
This method reports the cluster size for every connected volume in a single table.
@echo off
setlocal
echo [INFO] Cluster size inventory for all volumes:
echo --------------------------------------------------
powershell -NoProfile -Command ^
"$volumes = Get-CimInstance Win32_Volume |" ^
" Where-Object { $_.DriveLetter -and $_.FileSystem };" ^
"if (-not $volumes) {" ^
" Write-Host 'No volumes with drive letters found.';" ^
" exit 0" ^
"};" ^
"$volumes | ForEach-Object {" ^
" $clusterKB = if ($_.BlockSize) { [math]::Round($_.BlockSize / 1024) } else { 'N/A' };" ^
" $totalGB = [math]::Round($_.Capacity / 1GB, 1);" ^
" [PSCustomObject]@{" ^
" Drive = $_.DriveLetter;" ^
" FileSystem = $_.FileSystem;" ^
" 'Cluster (KB)' = $clusterKB;" ^
" 'Cluster (bytes)' = if ($_.BlockSize) { $_.BlockSize } else { 'N/A' };" ^
" Label = if ($_.Label) { $_.Label } else { '(none)' };" ^
" 'Size (GB)' = $totalGB" ^
" }" ^
"} | Sort-Object Drive | Format-Table -AutoSize"
echo --------------------------------------------------
endlocal
exit /b 0
Sample output:
[INFO] Cluster size inventory for all volumes:
--------------------------------------------------
Drive FileSystem Cluster (KB) Cluster (bytes) Label Size (GB)
----- ---------- ------------ --------------- ----- ---------
C: NTFS 4 4096 Windows 476.9
D: NTFS 64 65536 SQLData 931.5
E: exFAT 32 32768 BACKUP_USB 119.2
F: FAT32 4 4096 CAMERA_SD 29.7
What to look for:
- C: (OS drive) with non-default cluster size: Unusual. Most OS installations use 4 KB. A different size may indicate a special installation process.
- Database/VM drives with 4 KB clusters: SQL Server and Hyper-V perform best with 64 KB clusters. Consider reformatting these volumes.
- Large cluster sizes on drives with many small files: Significant space waste. Consider whether the performance benefit justifies the wasted space.
- Different cluster sizes across similar-purpose drives: Inconsistency may indicate drives were formatted at different times or with different tools.
Method 3: Cluster Size Recommendation Engine
For drive planning and formatting decisions, this method analyzes a drive's current content and suggests the optimal cluster size.
@echo off
setlocal
set "Drive=%~1"
if "%Drive%"=="" (
echo Usage: %~nx0 ^<drive_letter^>
echo.
echo Analyzes drive content and recommends optimal cluster size.
endlocal
exit /b 1
)
set "DriveLetter=%Drive:~0,1%"
set "DriveColon=%DriveLetter%:"
if not exist %DriveColon%\ (
echo [ERROR] Drive %DriveColon% not found. >&2
endlocal
exit /b 1
)
echo [INFO] Analyzing %DriveColon% content for cluster size recommendation...
echo [INFO] This may take a moment on large drives...
echo.
powershell -NoProfile -Command ^
"$drive = '%DriveColon%';" ^
"$files = @(Get-ChildItem -Path $drive -Recurse -File -Force -ErrorAction SilentlyContinue);" ^
"$totalFiles = $files.Count;" ^
"if ($totalFiles -eq 0) { Write-Host 'No files found or access denied.'; exit 0 };" ^
"$avgSize = [math]::Round(($files | Measure-Object Length -Average).Average / 1KB, 1);" ^
"$medianSize = ($files | Sort-Object Length | Select-Object -Index ([math]::Floor($totalFiles / 2))).Length;" ^
"$medianKB = [math]::Round($medianSize / 1KB, 1);" ^
"$smallFiles = @($files | Where-Object { $_.Length -lt 4096 }).Count;" ^
"$largeFiles = @($files | Where-Object { $_.Length -gt 10MB }).Count;" ^
"$smallPct = [math]::Round($smallFiles / $totalFiles * 100, 1);" ^
"$largePct = [math]::Round($largeFiles / $totalFiles * 100, 1);" ^
"Write-Host (' Total files: ' + $totalFiles);" ^
"Write-Host (' Average size: ' + $avgSize + ' KB');" ^
"Write-Host (' Median size: ' + $medianKB + ' KB');" ^
"Write-Host (' Small (<4 KB): ' + $smallFiles + ' (' + $smallPct + '%%)');" ^
"Write-Host (' Large (>10 MB): ' + $largeFiles + ' (' + $largePct + '%%)');" ^
"Write-Host '';" ^
"Write-Host ' Recommendation:';" ^
"if ($largePct -gt 50 -and $smallPct -lt 10) {" ^
" Write-Host ' 64 KB - Drive is dominated by large files.' -ForegroundColor Green;" ^
" Write-Host ' Optimal for sequential I/O performance.'" ^
"} elseif ($smallPct -gt 60) {" ^
" Write-Host ' 4 KB - Drive has many small files.' -ForegroundColor Green;" ^
" Write-Host ' Minimizes wasted space from partial cluster allocation.'" ^
"} else {" ^
" Write-Host ' 4 KB (default) - Mixed file sizes.' -ForegroundColor Green;" ^
" Write-Host ' Best general-purpose balance of space and performance.'" ^
"}"
endlocal
exit /b 0
Sample output:
[INFO] Analyzing D:\ content for cluster size recommendation...
[INFO] This may take a moment on large drives...
Total files: 12458
Average size: 12.4 KB
Median size: 2.1 KB
Small (<4 KB): 7890 (63.3%)
Large (>10 MB): 124 (1.0%)
Recommendation:
4 KB - Drive has many small files.
Minimizes wasted space from partial cluster allocation.
When to use non-default cluster sizes:
| Workload | Recommended | Rationale |
|---|---|---|
| General purpose / OS drive | 4 KB | Balanced space/performance; NTFS default |
| SQL Server data files | 64 KB | Microsoft recommendation; maximizes sequential throughput |
| Hyper-V virtual disks | 64 KB | Reduces metadata overhead for large VHDX operations |
| Video editing / media | 64 KB | Large sequential files benefit from fewer allocation units |
| Source code repositories | 4 KB | Many small files; 64 KB would waste 90%+ space |
| Log file storage | 4–16 KB | Balance between log file size and write efficiency |
Method 4: Fleet-Wide Cluster Size Audit
For auditing cluster sizes across multiple machines, essential for verifying database servers have the recommended 64 KB allocation.
@echo off
setlocal
set "CSVFile=\\Server\Audit\cluster_size_inventory.csv"
if not exist "%CSVFile%" (
echo "Timestamp","Computer","Drive","FileSystem","ClusterBytes","ClusterKB","Label","SizeGB" > "%CSVFile%" 2>nul
)
powershell -NoProfile -Command ^
"$ts = Get-Date -Format 'yyyy-MM-dd HH:mm:ss';" ^
"Get-CimInstance Win32_Volume |" ^
" Where-Object { $_.DriveLetter -and $_.FileSystem } |" ^
" ForEach-Object {" ^
" $clusterKB = if ($_.BlockSize) { [math]::Round($_.BlockSize / 1024) } else { 'N/A' };" ^
" $sizeGB = [math]::Round($_.Capacity / 1GB, 1);" ^
" $label = if ($_.Label) { $_.Label } else { 'none' };" ^
" Write-Output ('\"' + $ts + '\",\"' + $env:COMPUTERNAME + '\",\"' + $_.DriveLetter + '\",\"' + $_.FileSystem + '\",\"' + $_.BlockSize + '\",\"' + $clusterKB + '\",\"' + $label + '\",\"' + $sizeGB + '\"')" ^
" }" >> "%CSVFile%" 2>nul
echo [OK] Cluster size data exported for %COMPUTERNAME%.
endlocal
exit /b 0
What to look for in the fleet CSV:
- SQL Server machines with 4 KB clusters on data drives: Should be 64 KB per Microsoft best practices. Reformatting may be worth scheduling during a maintenance window.
- Hyper-V hosts with 4 KB clusters on VM storage: 64 KB improves VHDX performance.
- Inconsistent cluster sizes across similar-role servers: May indicate non-standardized provisioning processes.
How to Avoid Common Errors
Wrong Way: Assuming 4 KB Is Universal
:: WRONG - not all NTFS volumes use 4 KB
echo Cluster size is 4096 bytes (assumed)
Volumes may have been formatted with non-default cluster sizes. Volumes larger than 16 TB default to larger cluster sizes. Some deployment tools set specific cluster sizes.
Correct Way: Always query the actual cluster size (Methods 1–2). Never assume.
Wrong Way: Using fsutil fsinfo ntfsinfo on Non-NTFS Drives
:: FAILS on FAT32, exFAT, and ReFS volumes
fsutil fsinfo ntfsinfo E:
fsutil fsinfo ntfsinfo is NTFS-specific. It fails on FAT32, exFAT, and ReFS volumes.
Correct Way: Use Win32_Volume.BlockSize (as shown in all methods), which works for any file system type.
Problem: Cannot Change Cluster Size Without Reformatting
Once a volume is formatted, its cluster size is permanently set. There is no resize cluster command.
Solution: To change the cluster size:
- Back up all data from the volume.
- Format the volume with the new cluster size:
format D: /fs:ntfs /a:65536 /q(for 64 KB clusters). - Restore the data.
The /a: parameter of the format command sets the allocation unit size in bytes.
Problem: fsutil Requires Admin Privileges
Most fsutil commands require elevation. Running without admin produces "Error: Access is denied."
Solution: All methods in this guide use PowerShell with Get-CimInstance Win32_Volume, which works without elevation for read-only queries on most systems.
Best Practices and Rules
1. Use 4 KB for General-Purpose Drives
Unless you have a specific workload that benefits from larger clusters (databases, VMs, media editing), the default 4 KB provides the best balance.
2. Use 64 KB for SQL Server and Hyper-V
Microsoft explicitly recommends 64 KB allocation units for SQL Server data volumes and Hyper-V virtual disk storage. This is a well-documented best practice that measurably improves performance.
3. Document the Cluster Size When Formatting
When provisioning new servers, record the cluster size used for each volume. This avoids the need to query it later and ensures consistency across the fleet.
4. Audit Database Servers Regularly
Use Method 4 to verify that database and VM storage volumes maintain the recommended 64 KB cluster size. Drives added or reformatted after initial provisioning may revert to the 4 KB default.
5. Consider Cluster Size Before Large Deployments
Changing the cluster size after the volume is in production requires a backup-format-restore cycle (downtime). Getting it right during initial formatting avoids this disruption.
Conclusions
Querying the cluster size of your volumes provides deep insight into storage performance characteristics and space efficiency. By using Win32_Volume.BlockSize for cross-filesystem compatibility, providing workload-specific recommendations, and auditing cluster sizes across your fleet, you can make informed decisions about formatting strategies and identify volumes that may benefit from optimization. This level of detail is essential for database administrators, virtualization engineers, and anyone who needs to maximize storage performance.