How to Monitor Disk Space and Alert When Low in Batch Script
Running out of disk space on a server can lead to catastrophic failures, databases crash, logs stop writing, and system updates fail. Manually checking free space every day is a tedious task that is easily forgotten. A Batch script can automate this monitoring by querying the system for available space and triggering a warning when free space drops below a defined threshold.
This guide will explain how to check disk space reliably and trigger an alert.
Why PowerShell Is Necessary for Disk Space Math
Batch arithmetic is limited to 32-bit signed integers, a maximum value of 2,147,483,647 (approximately 2 GB). Since even a modest modern drive has tens or hundreds of gigabytes free, the raw byte counts exceed this limit by orders of magnitude. Any attempt to compare or calculate disk space using set /a will silently overflow and produce incorrect results.
For this reason, all disk space comparisons in this guide delegate the math to PowerShell, which handles 64-bit integers natively. The Batch script serves as the orchestrator, calling PowerShell for the calculation, receiving a simple pass/fail result, and acting on it.
Method 1: Basic Disk Space Check
This method uses a minimal PowerShell snippet to compare free space against a threshold and returns an exit code that Batch can evaluate.
@echo off
setlocal
set "Drive=C:"
set "MinGB=50"
echo [INFO] Checking disk space on %Drive%...
:: Use PowerShell for 64-bit math, returns exit code 1 if below threshold
powershell -NoProfile -Command ^
"$driveInfo = Get-PSDrive -Name '%Drive:~0,1%' -ErrorAction SilentlyContinue;" ^
"if (-not $driveInfo) { Write-Error 'Drive not found'; exit 2 };" ^
"$freeGB = [math]::Floor($driveInfo.Free / 1GB);" ^
"Write-Host \"Free space: $freeGB GB\";" ^
"if ($freeGB -lt %MinGB%) { exit 1 } else { exit 0 }"
set "PSResult=%errorlevel%"
if %PSResult% equ 2 (
echo [ERROR] Drive %Drive% was not found or is not accessible. >&2
endlocal
exit /b 1
)
if %PSResult% equ 1 (
echo [WARNING] Disk space on %Drive% is below %MinGB% GB!
echo [WARNING] Action required - free up space or expand the volume.
) else (
echo [OK] Sufficient disk space available on %Drive%.
)
endlocal
exit /b %PSResult%
Why Get-PSDrive instead of wmic:
wmicis deprecated as of Windows 10 21H1 and may be removed in future Windows versions.Get-PSDriveis available in all PowerShell versions (2.0+) and returns theFreeandUsedproperties directly.- PowerShell handles 64-bit arithmetic natively, eliminating the overflow problems that make pure Batch math unusable for disk space.
Method 2: Multi-Drive Monitoring with Logging
For server environments, you typically need to monitor multiple drives and write results to a log file rather than displaying popups. This method checks every fixed local drive and logs the results.
@echo off
setlocal enabledelayedexpansion
set "MinGB=20"
set "LogFile=%~dp0diskcheck.log"
set "TempFile=%~dp0drives.tmp"
set "AlertTriggered=FALSE"
echo [%date% %time%] Disk space check started >> "%LogFile%"
:: Run the PowerShell command and save the output to a temp file
powershell -NoProfile -Command "Get-CimInstance Win32_LogicalDisk -Filter 'DriveType=3' | ForEach-Object { $free = [math]::Floor($_.FreeSpace / 1GB); Write-Host ($_.DeviceID + ' ' + $free) }" > "%TempFile%"
:: Read the temp file
for /f "tokens=1,2" %%a in (%TempFile%) do (
set "Drive=%%a"
set "Free=%%b"
if !Free! LSS %MinGB% (
echo [%date% %time%] Drive !Drive!: !Free! GB free [LOW] >> "%LogFile%"
echo [WARNING] Drive !Drive! has only !Free! GB free (threshold: %MinGB% GB^) >&2
set "AlertTriggered=TRUE"
) else (
echo [%date% %time%] Drive !Drive!: !Free! GB free [OK] >> "%LogFile%"
echo [OK] Drive !Drive!: !Free! GB free.
)
)
del "%TempFile%"
if "%AlertTriggered%"=="TRUE" (
echo [%date% %time%] *** LOW DISK SPACE ALERT *** >> "%LogFile%"
exit /b 1
)
echo [%date% %time%] All drives OK. >> "%LogFile%"
echo [OK] All drives have sufficient space.
exit /b 0
How this works:
- PowerShell queries all fixed local drives (
DriveType=3excludes CD-ROMs, USB, and network shares). - For each drive, it calculates free space in GB and outputs a simple three-token line:
DriveLetter FreeGB Status. - The Batch
for /floop parses each line, logs the result, and flags any drive that is below the threshold. - The script exits with code
1if any drive triggered an alert, or0if all drives are healthy.
Why Get-WmiObject here instead of Get-CimInstance:
Both work for this purpose. Get-WmiObject is used here because it is available in PowerShell 2.0 (Windows 7), maximizing compatibility. If your environment is Windows 10+ only, you can substitute Get-CimInstance Win32_LogicalDisk for the same result.
Method 3: Alerting Mechanisms
When disk space is low, the script needs to notify someone. The right alerting mechanism depends on your environment.
Option A: Windows Event Log (Recommended for Servers)
Writing to the Windows Event Log allows existing monitoring tools (SCOM, Zabbix, Nagios, etc.) to pick up the alert automatically.
:: Write a warning event to the Application log
:: Event ID 1001, Source "DiskMonitor"
if "%AlertTriggered%"=="TRUE" (
eventcreate /T WARNING /ID 1001 /L APPLICATION /SO DiskMonitor ^
/D "Low disk space detected on one or more drives. Check %LogFile% for details." >nul 2>&1
)
Option B: Email via PowerShell
For environments without centralized monitoring:
if "%AlertTriggered%"=="TRUE" (
powershell -NoProfile -Command ^
"Send-MailMessage -From 'monitor@company.com' -To 'admin@company.com'" ^
" -Subject 'ALERT: Low Disk Space on %COMPUTERNAME%'" ^
" -Body (Get-Content '%LogFile%' -Raw)" ^
" -SmtpServer 'mail.company.com'"
)
Option C: Console Message (msg command)
For interactive desktop environments only. Note that msg requires Terminal Services and may not work on all editions:
if "%AlertTriggered%"=="TRUE" (
msg * "Warning: Low disk space detected on %COMPUTERNAME%. Check %LogFile%." 2>nul
)
How to Avoid Common Errors
Wrong Way: Using Batch Arithmetic for Byte Counts
:: BROKEN: overflows silently for any value above ~2 GB
set /a "FreeGB=%FreeBytes% / 1073741824"
Batch set /a is limited to 32-bit signed integers (max 2,147,483,647). A drive with 100 GB free has approximately 107,374,182,400 bytes, far beyond this limit. The calculation silently overflows and produces a meaningless number.
Correct Way: Delegate all large-number math to PowerShell, which handles 64-bit integers natively.
Wrong Way: Parsing dir Output for Free Space
The summary line of dir (e.g., 15,234,120 bytes free) changes format depending on the user's regional settings, commas vs. periods for thousands separators, different text for "bytes free" in non-English locales.
Correct Way: Use PowerShell's Get-PSDrive or Get-WmiObject Win32_LogicalDisk, which return raw numeric values regardless of locale.
Wrong Way: Using wmic in New Scripts
wmic.exe is deprecated since Windows 10 21H1. While it still works on most current systems, Microsoft may remove it in future Windows releases.
Correct Way: Use PowerShell cmdlets (Get-PSDrive, Get-CimInstance, Get-WmiObject) for new scripts. If you must support systems without PowerShell (extremely rare), wmic remains a last resort.
Problem: The msg Command Fails Silently
The msg command requires Terminal Services and may not be available on all Windows editions (notably some Home editions). It also cannot reach users on remote machines without additional configuration.
Solution: Use msg only as a supplementary alert for interactive desktop sessions, with 2>nul to suppress errors when it is unavailable. Rely on Event Log entries or email for primary alerting.
Best Practices and Rules
1. Alert Frequency and Deduplication
If this script runs as a scheduled task every hour, a persistently full drive will generate 24 alerts per day. Consider writing a "last alert" timestamp to a file and suppressing duplicate alerts within a cooldown period (e.g., once every 4 hours).
2. Monitor Multiple Drives Automatically
Use Method 2 to enumerate all fixed drives automatically rather than hardcoding drive letters. Drives can be added or removed from servers over time, and a hardcoded list will miss new volumes.
3. Log to a File, Not Just the Screen
Scheduled tasks have no visible console. Always write results to a log file so you have a historical record of disk space trends. Include timestamps in every log entry.
4. Set Appropriate Thresholds
A 20 GB threshold is reasonable for a system drive, but may be far too aggressive for a 10 TB data volume (where 20 GB free represents 0.2%). Consider using percentage-based thresholds for large drives:
:: PowerShell snippet for percentage-based check
powershell -NoProfile -Command ^
"$disk = Get-WmiObject Win32_LogicalDisk -Filter \"DeviceID='C:'\";" ^
"$pctFree = [math]::Round(($disk.FreeSpace / $disk.Size) * 100, 1);" ^
"Write-Host \"$pctFree%% free\";" ^
"if ($pctFree -lt 10) { exit 1 } else { exit 0 }"
Conclusions
Automating disk space monitoring is a fundamental part of proactive server maintenance. By delegating large-number math to PowerShell and using structured alerting (Event Log, email, or log files), you ensure that your systems provide early warning before a "Disk Full" crisis begins. Running this as a scheduled task gives you continuous, hands-off vigilance over your storage infrastructure.