The .bat extension dates back to MS-DOS (Disk Operating System) where it stood for "batch" processing. When Windows NT introduced the enhanced command interpreter cmd.exe, Microsoft introduced the .cmd extension to distinguish newer scripts from legacy DOS batch files.
While both file types are executed by the command interpreter, their processing varies slightly:
@echo off
:: Example showing ERRORLEVEL handling difference
command_that_fails
if errorlevel 1 (
echo This behaves differently in .bat vs .cmd
)
.cmd files implement more robust error handling similar to modern scripting:
:: In a .cmd file this works as expected
set /a result=10/0 2>nul || (
echo Division by zero caught properly in .cmd
)
.cmd files introduce better variable scoping rules:
setlocal
set var=outer
(
set var=inner
echo !var! :: Works in .cmd, fails in .bat
)
endlocal
Practical recommendations based on project requirements:
- Use .bat for maximum compatibility with ancient systems (DOS-era)
- Use .cmd for modern Windows environments (NT+)
- For new projects, prefer .cmd for better error handling
Feature | .bat | .cmd |
---|---|---|
Delayed expansion | Limited | Full support |
Errorlevel handling | Basic | Enhanced |
Script nesting | Restrictions | Better support |
Back in the MS-DOS days, batch files exclusively used the .BAT extension (short for "batch"). When Windows NT introduced the modern command processor (cmd.exe), Microsoft added the .CMD extension to distinguish NT-specific scripts from DOS-compatible ones.
While both file types execute similarly in modern Windows, subtle differences exist:
@echo off
:: This works in both .bat and .cmd
echo Hello World
Key distinctions:
- Error handling differs: .CMD files exit on errors by default
- Environment variable scope varies slightly
- .CMD files support more advanced syntax in modern Windows
In contemporary Windows environments:
:: Preferred .cmd format for modern scripting
@echo off
setlocal enabledelayedexpansion
:: Error handling example
if not exist "C:\temp" (
echo Directory doesn't exist & exit /b 1
)
Most organizations standardize on .CMD for:
- NT-specific features
- Better error handling
- Clearer intent (modern vs legacy)
Use .BAT when:
:: Simple .bat example for maximum compatibility
echo This runs everywhere
pause
- Targeting multiple Windows versions
- Needing DOS compatibility
- Maintaining legacy systems
For new scripts in 2023+, I recommend:
:: Modern .cmd template
@echo off
setlocal enabledelayedexpansion
:: Main script logic
if "%1"=="" (
echo Usage: %~n0 ^
exit /b 1
)
:: Proper error handling
somecommand.exe || (
echo Error executing somecommand & exit /b 1
)