codingstairs
NotesEDULifeContact
⌕Search⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

Get in touch

Send without signing in. Add your email if you'd like a reply.

  • Leave a message anonymously →
  • ✉ warragon112@gmail.com
  • KakaoTalk Open Chat ↗

© 2026 codingstairs

  • Notes
  • EDU
  • Search
  • Life
  • Contact
  • Legal
  • RSS
  • GitHub
Notes›environment

cmd.exe and batch files

Published 2026-04-28· Updated 2026-05-18·0 views

cmd.exe and batch files

cmd.exe is the command processor on Windows NT-family systems. It debuted in 1993 with Windows NT 3.1 and ships with every Windows release. Since PowerShell arrived, cmd's role as an entry point for new code has shrunk, but we still meet it through legacy compatibility and small quick tasks.

1. Where cmd.exe sits

  • MS-DOS era — COMMAND.COM was the 16-bit command processor.
  • From Windows NT 3.1 (1993) — the 32-bit cmd.exe became the standard command processor on the NT line.
  • It keeps a large share of DOS command compatibility, but adds new features (pipe handling, command extensions).

PowerShell is more capable, but cmd lives on for the following reasons:

  • The lightest available shell. Usable immediately right after boot.
  • A great many old automation scripts and installers still ship as .bat.
  • Environment entry scripts like Visual Studio Developer Command Prompt are cmd-based.

2. .bat vs .cmd

  • .bat — the DOS-era extension. Compatibility first.
  • .cmd — introduced with Windows NT. Some built-in commands update errorlevel differently from .bat (append, dpath, ftype, set, path, assoc, prompt). .cmd is recommended for new files.

In practice the two are usually treated as the same thing.

3. Basic syntax

@echo off
setlocal enabledelayedexpansion

set NAME=world
echo hello, %NAME%

if "%NAME%"=="world" (
  echo matched
) else (
  echo no match
)

for %%f in (*.txt) do (
  echo %%f
)

endlocal

Key elements:

  • @echo off — keeps subsequent commands from being echoed before they run.
  • setlocal / endlocal — limits variable scope to the script.
  • enabledelayedexpansion — enables !var! delayed expansion. Even when a variable is updated inside a for/if block, it reflects immediately.
  • %var% — normal variable reference. Substituted once when the block is entered.
  • !var! — delayed expansion. Re-evaluated each iteration.
  • if errorlevel N — true when the last command's exit code is N or above. The exact code is %ERRORLEVEL%.

4. Variants of for

for %%f in (*.log) do echo %%f         :: file list
for /R %%f in (*.md) do echo %%f       :: recurse
for /L %%i in (1,1,5) do echo %%i      :: 1..5
for /F "tokens=1,2" %%a in (file.txt) do echo %%a %%b   :: parse file lines

Inside scripts use %%f, on the command line use a single percent %f.

5. Functions (label + call)

@echo off
call :greet alice
exit /b 0

:greet
echo hello, %~1
exit /b 0

exit /b N returns N to the caller. %~1 strips surrounding quotes from the first argument.

6. Code pages and Korean

cmd.exe defaults to cp949 on a Korean Windows install (Microsoft's extension to EUC-KR). Printing a UTF-8 file as is breaks Korean characters.

Task Command
Check current code page chcp
Switch to UTF-8 (current session) chcp 65001
Switch to cp949 chcp 949

chcp 65001 can break output on certain font/console-host combinations and in some external exes. It is relatively stable on Windows 11 + Windows Terminal.

The script file's own encoding is safest saved as cp949 (ANSI). When saving as UTF-8 the BOM presence can affect cmd's behavior.

7. bash equivalents

Task bash cmd
Set variable FOO=bar set FOO=bar
Read variable $FOO %FOO%
Export env var export FOO=bar set FOO=bar
Directory listing ls dir
Current location pwd cd (no arg)
Clear screen clear cls
View file cat file type file
Exit code $? %ERRORLEVEL%
Conditional (success) a && b a && b (cmd supports it)
Conditional (failure) `a
Comment # ... REM ... or :: ...

8. Limits

No object or module system. PowerShell or another language fits large-scale automation better.

Weak string handling and data structures. Arrays are simulated through index variables.

Unicode handling is awkward. Encoding mismatches between console output, file I/O, and external commands happen easily.

Debugging tooling is thin. Tracing usually means scattering echo calls.

9. Same task in cmd vs bash

@echo off
setlocal
if not exist build mkdir build
cd build
echo build directory ready
endlocal
#!/usr/bin/env bash
set -euo pipefail
mkdir -p build
cd build
echo "build directory ready"

10. Common pitfalls

set FOO = bar with spaces around = makes the variable name FOO (with trailing space) — keep it as set FOO=bar.

%var% not refreshing inside a for block — fix with setlocal enabledelayedexpansion + !var!.

Double-clicking a batch file closes the window the moment it finishes, hiding output — add pause at the end or run from cmd directly.

Korean text breaking — both code page and file encoding need to match.

if "%var%"=="value" becomes if ""=="value" when the variable is empty. The syntax still parses but the intent gets murky — keep the quotes around the variable consistent.

Closing thoughts

cmd and batch files sit in the legacy-compatibility seat. New automation lands more naturally in PowerShell or bash, with .bat reduced to an entry-point wrapper. Korean encoding and delayed expansion are the two spots where things go wrong most often.

Next

  • cross-platform-scripts
  • markdown

Microsoft Windows commands · Microsoft cmd · SS64 CMD · Microsoft chcp · Wikipedia cmd.exe for reference.

More in environment

All in this category →
  • WSL2 — Linux on top of Windows
  • Data formats — JSON · YAML · TOML · XML
  • First day with the terminal
  • Text encoding and line endings
  • Markdown
  • Cross-platform scripts