cmd.exe 와 배치 파일
cmd.exe 와 배치 파일
cmd.exe 는 Windows NT 계열의 명령 처리기입니다. 1993 년 Windows NT 3.1 부터 등장해 지금도 모든 Windows 에 포함. PowerShell 이 등장한 이후로는 새 코드의 진입점 역할은 줄었지만, 레거시 호환과 빠른 작은 작업에서 여전히 마주칩니다.
1. cmd.exe 의 위치
- MS-DOS 시절 —
COMMAND.COM이 16비트 명령 처리기. - Windows NT 3.1 (1993) 부터 — 32비트
cmd.exe가 도입되어 NT 기반의 표준 명령 처리기. - DOS 명령 호환을 상당 부분 유지하지만 새 기능 (파이프 처리 · 명령 확장) 추가.
PowerShell 이 더 강력하지만 cmd 는 다음 이유로 살아 있습니다:
- 가장 가벼움. 부팅 직후 바로 사용 가능.
- 오래된 자동화 스크립트와 설치 프로그램이 여전히
.bat으로 배포. - Visual Studio Developer Command Prompt 같은 환경 진입 스크립트가 cmd 기반.
2. .bat 와 .cmd 의 차이
.bat— DOS 시대부터의 확장자. 호환성 우선..cmd— Windows NT 에서 도입. 일부 내장 명령 실행 후 errorlevel 갱신 동작이.bat과 다름 (append·dpath·ftype·set·path·assoc·prompt). 신규 작성에는.cmd권장.
실무에서는 둘을 사실상 같은 것으로 다루어도 무방한 경우가 대부분.
3. 기본 문법
@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
핵심 요소:
@echo off— 이후 명령들이 실행 전에 화면에 출력되지 않게.setlocal/endlocal— 변수 영역을 스크립트 안으로 한정.enabledelayedexpansion—!var!형식의 지연 확장.for/if블록 안에서 변수가 갱신되어도 즉시 반영.%var%— 일반 변수 참조. 블록 진입 시점에 한 번에 치환.!var!— 지연 확장. 매 반복마다 다시 평가.if errorlevel N— 마지막 명령의 종료 코드가 N 이상인지. 정확한 코드는%ERRORLEVEL%.
4. for 의 변형
for %%f in (*.log) do echo %%f :: 파일 목록
for /R %%f in (*.md) do echo %%f :: 재귀
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 :: 파일 라인 파싱
스크립트 안에서는 %%f, 명령줄에서는 %f 로 단일 퍼센트.
5. 함수 (label + call)
@echo off
call :greet alice
exit /b 0
:greet
echo hello, %~1
exit /b 0
exit /b N 은 호출자에게 N 으로 돌아감. %~1 은 첫 번째 인자에서 둘러싼 따옴표를 제거한 값.
6. 코드 페이지와 한글
cmd.exe 의 기본 코드 페이지는 한국어 Windows 에서 cp949 (EUC-KR 의 Microsoft 확장). UTF-8 파일을 그대로 출력하면 한글이 깨집니다.
| 작업 | 명령 |
|---|---|
| 현재 코드 페이지 확인 | chcp |
| UTF-8 로 전환 (현재 세션) | chcp 65001 |
| cp949 로 전환 | chcp 949 |
chcp 65001 은 일부 글꼴·콘솔 호스트 조합에서 출력이 깨지거나 일부 외부 exe 와 호환 문제. Windows 11 + Windows Terminal 조합에서는 비교적 안정적.
스크립트 파일 자체의 인코딩은 cp949 (ANSI) 로 저장하는 편이 가장 안전. UTF-8 로 저장할 때는 BOM 유무가 cmd 의 동작에 영향을 줄 수 있음.
7. bash 등가 비교
| 작업 | bash | cmd |
|---|---|---|
| 변수 설정 | FOO=bar |
set FOO=bar |
| 변수 읽기 | $FOO |
%FOO% |
| 환경변수 export | export FOO=bar |
set FOO=bar |
| 디렉터리 목록 | ls |
dir |
| 현재 위치 | pwd |
cd (인자 없이) |
| 화면 비우기 | clear |
cls |
| 파일 보기 | cat file |
type file |
| 종료 코드 | $? |
%ERRORLEVEL% |
| 조건 (성공시) | a && b |
a && b (cmd 지원) |
| 조건 (실패시) | `a | |
| 주석 | # ... |
REM ... 또는 :: ... |
8. 한계
객체나 모듈 시스템이 없습니다. 대규모 자동화에는 PowerShell 이나 다른 언어가 적합.
문자열 처리·자료구조가 빈약. 배열은 인덱스 변수로 직접 흉내.
유니코드 처리가 까다로움. 콘솔 출력·파일 입출력·외부 명령 사이의 인코딩이 어긋나기 쉬움.
디버깅 도구가 약함. 보통 echo 로 추적.
9. 같은 작업의 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. 자주 걸리는 자리
set FOO = bar 처럼 = 양옆에 공백을 두면 변수명이 FOO (공백 포함) — 공백 없이 set FOO=bar.
for 블록 안에서 %var% 가 제 값으로 갱신 안 됨 — setlocal enabledelayedexpansion + !var! 로 해결.
배치 파일을 더블클릭으로 실행하면 끝나는 즉시 창이 닫혀 출력이 안 보임 — pause 를 마지막에 넣거나 cmd 에서 직접 호출.
한글 깨짐 — 코드 페이지와 파일 인코딩 양쪽이 맞아야 함.
if "%var%"=="value" 에서 %var% 가 비어 있으면 if ""=="value" 가 되어 구문은 동작하지만 의도가 모호 — 변수 양쪽을 따옴표로 감싸는 패턴 일관되게.
하고픈 말
cmd 와 배치 파일은 레거시 호환의 자리. 신규 자동화는 PowerShell 또는 bash 가 자연스럽고, .bat 은 진입점 wrapper 로만 두는 모양이 깔끔합니다. 한글 인코딩과 지연 확장 두 자리가 가장 자주 사고 나는 곳.
Next
- cross-platform-scripts
- markdown
Microsoft Windows 명령 · Microsoft cmd · SS64 CMD · Microsoft chcp · Wikipedia cmd.exe 를 참고합니다.