저도 초보 수준인데 이런 말씀 드리긴 뭐하지만, 이 글은 초보 분들에게 별 재미가 없을테니 초보 분들은 그냥 넘겨주세요. 배치파일 자주 작성하시는 분들을 위한 글입니다.
저는 FOR 구문에 대해 특별히 공부한 것이 없습니다. 그냥 /? 붙여서 나온 도움말을 보고 익힌게 다입니다. 그래서 여기서 다룰 내용은 매우 기초적인 것들입니다. 하지만 이러한 기초적인 내용을 익혀두면 응용하기에 따라 매우 편리하게 사용할 수 있습니다. 제가 윈도우 하드에서 설치하기나 PE, VHD 관련 글에 첨부하는 스크립트에는 대부분 FOR 구문이 포함되어 있습니다. 조금만 익혀두면 적어도 제가 사용하는 수준만큼은 도달할 수 있습니다.
1. 기본 구조
for /f "옵션" %변수 in (메롱) do 명령어
FOR 구문의 기본 구조입니다. (메롱) 안에 있는 문자열, 파일, 명령어의 출력값 등에 대해 DO 이하 명령어를 반복 수행하도록 지시합니다. 그런데 %변수의 경우 일괄 배치파일 안에 들어갈 때는 %%변수 형태로 적어줘야 합니다. 또한 %변수는 대소문자를 구분합니다. 즉 %a와 %A는 다릅니다.
예제)
for %a in (*.msu) do start /wait wusa %a /quiet /norestart
위 예는 현재 위치에 존재하는 확장자 msu 파일에 대해 wusa라는 "윈도우 업데이트 독립 실행형 설치 관리자" 툴을 사용하여 반복해서 설치를 수행합니다. 아 물론 이건 윈도우 비스타, 세븐 기준입니다.
XP 업데이트라면 아래 예제처럼 하면 되겠지요.
예제)
for %a in (*.exe) do start /wait %a /quiet /norestart
위 예는 현재 위치에 존재하는 확장자 exe 파일에 대해 반복해서 실행을 수행합니다.
예제)
for %%a in (C: D: E: F: G: H: I: J: K: L: M: N: O: P: Q: R: S: T: U: V: W: X: Y: Z:) do (
if exist %%a\WIN51 set CDROM=%%a
)
위 예는 C ~ Z 드라이브 중에 WIN51 이라는 파일을 포함하고 있다면 해당 드라이브를 CDROM 이라는 변수로 지정해줍니다. 제가 WIN51 이라는 태그파일을 넣은 이유는 XP 설치 CD를 예로 든 것입니다. 만약 XP 무인설치를 구성하는데 추가 프로그램이 CD롬에서 실행되어야 한다면 CD롬 드라이브 문자를 알아내기 위해 저렇게 사용할 수 있겠지요. 이렇게 한번 지정해두면 예를 들어 CD롬 안에 UTILS 폴더가 있고 그 안에 있는 AAA.EXE 파일을 실행해야 한다면
%CDROM%\UTILS\AAA.EXE
위 예처럼 넣으면 되겠지요.
2. 옵션
저는 tokens= 옵션이 FOR 구문의 꽃이라 생각합니다. 토큰을 잘 활용하면 재미있는 스크립트를 많이 만들어낼 수 있습니다. 제가 자주 사용하는 옵션 몇가지만 간단히 설명드리겠습니다.
tokens=
FOR 구문은 각 행별로 분석하는데 이때 토큰은 각 행의 몇번째 문자열을 전달해줄지 지정합니다. 문자열의 기본 구분단위는 공백입니다.
for /f "tokens=3" %a in ("I LOVE YOU") do echo %a
위 예제를 입력하면 결과가 어떻게 될까요? 바로 세번째 문자열인 YOU가 출력됩니다. 토큰이 뭔지 이해되시죠?
delims=
토큰은 기본적으로 공백으로 구분하는데 delims 뒤에 구분 문자를 지정하면 그걸로 대체됩니다.
for /f "tokens=3" %a in ("I LOVE YOU-SO MUCH") do echo %a
for /f "tokens=2 delims=-" %a in ("I LOVE YOU-SO MUCH") do echo %a
for /f "tokens=4 delims=- " %a in ("I LOVE YOU-SO MUCH") do echo %a
위 예제를 각각 입력해보시면 delims의 기능을 이해하실 수 있을겁니다.
첫번째 줄은 delims가 없기 때문에 공백이 구분 문자라서 세번째 토큰은 YOU-SO가 됩니다.
두번째 줄은 - 문자가 구분자라서 두번째 토큰은 SO MUCH가 됩니다.
세번째 줄은 - 와 공백이 동시에 구분자라서 네번째 토큰은 SO가 됩니다.
skip=
위에서부터 몇줄까지 무시할지 결정해줍니다. 필요한 토큰이 세번째 줄에 있다면 처음 두줄은 무시해줘도 되겠지요. 이 경우 skip=2 라고 입력하면 됩니다.
usebackq
이 옵션은 공백을 포함한 파일 경로 양쪽에 큰 따옴표를 붙여줄 때 사용합니다. 대신 이 옵션을 사용하면 괄호안에 들어갈 집합에 대한 표시를 조금 다르게 해야합니다. 원래는
(파일), ("문자열"), ('명령어') 인데 usebackq 옵션을 사용하면 ("파일"), ('문자열'), (`명령어`) 형태로 써야합니다.
예를 들어 MY NAME.TXT 라는 공백을 포함한 이름의 텍스트 파일이 존재하는 경우
for /f "tokens=1" %a in (MY NAME.TXT) do echo %a
for /f "tokens=1" %a in ("MY NAME.TXT") do echo %a
for /f "tokens=1 usebackq" %a in ("MY NAME.TXT") do echo %a
위 3가지 예중에 정상적으로 되는건 세번째밖에 없습니다.
첫번째 줄은 MY 라는 파일과 NAME.TXT 라는 파일을 찾기 때문에 실패하고
두번째 줄은 "MY NAME.TXT"를 파일 이름이 아닌 하나의 문자열로 인식하기 때문에 MY가 출력되고
세번째 줄만 원래 의도대로 MY NAME.TXT 파일 안에서 각 행의 첫번째 토큰을 출력해줍니다.
그러니까 FOR 구문에서 뒤쪽에 띄어쓰기 문제로 큰 따옴표를 사용해야 한다면 usebackq 옵션을 넣고 형식에 맞게 변경해야 합니다. 비단 괄호 안에 들어가는 파일 집합 뿐 아니라 DO 이하 구문에 들어가는 파일 경로에도 동일하게 적용된다는 점 알아두시면 됩니다.
/L
이 옵션은 단계적으로 증가, 감소하는 숫자 집합을 이용할 때 씁니다.
for /l %a in (1,1,5) do start /wait imagex /export h:\sources\install.wim %a e:\install.wim
위 예제는 Imagex로 윈도우 7 통합본 만들 때 일일이 export 시키는게 귀찮은 경우 사용할 수 있습니다. %a를 1부터 5까지 순서대로 받아주기 때문에 h:\sources\install.wim 이미지의 1~5 인덱스를 순서대로 e:\install.wim 파일로 export 시켜줄 수 있습니다. 만약 (5,-1,1) 하시면 5부터 1까지 차례대로 감소하면서 진행됩니다. 그러니까 (시작, 간격, 끝) 형태로 사용하시면 됩니다.
3. 실전 예제
현재 윈도우 7 사용중이신 분들의 에디션을 화면에 출력해보겠습니다. 에디션은 C:\Windows\System32\spp\tokens\skus 폴더 안을 보시면 확인이 가능합니다. 또는 레지스트리 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion 을 통해서도 확인할 수 있습니다. 이 두가지 방법을 각각 FOR 옵션에 적용해보겠습니다.
먼저 토큰 폴더를 활용하려면
dir /b C:\Windows\System32\spp\tokens\skus
이렇게 입력하면 저같은 경우
Security-SPP-Component-SKU-Ultimate
이렇게 출력되는데 이건 공백 기준으로 하나의 토큰이므로 delims=- 를 사용하여 구분해주면 에디션은 다섯번째 토큰이 됩니다.
@echo off
for /f "tokens=5 delims=-" %%a in ('dir /b %windir%\System32\spp\tokens\skus') do set sku=%%a
echo.
echo 당신은 현재 %SKU% 에디션을 사용하고 있습니다.
echo.
pause
exit
위 스크립트를 실행하면 화면에 에디션이 출력되겠지요?
다음은 레지스트리로 해봅시다.
reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v EditionID
이렇게 입력하면
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
EditionID REG_SZ Ultimate
저의 경우 이렇게 출력되는데 첫줄은 공백이고 에디션은 세번째 줄의 세번째 토큰입니다. 따라서 이렇게 구성하면 되겠네요.
@echo off
for /f "tokens=3 skip=2" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v EditionID') do set SKU=%%a
echo.
echo 당신은 지금 %SKU% 에디션을 사용하고 있습니다.
echo.
pause
exit
위 스크립트를 실행해도 마찬가지로 화면에 에디션이 출력됩니다.
위 두가지 예제를 어디에 활용할 수 있을까요? 예를 들어 윈도우 7 $OEM$ 배포폴더 SetupComplete.cmd 파일에 처리해주면 에디션을 자동으로 인식해서 시디키를 입력해줄 수 있겠지요?
@echo off
for /f "tokens=5 delims=-" %%a in ('dir /b %windir%\System32\spp\tokens\skus') do set sku=%%a
if /i %sku%==starter cscript %windir%\system32\slmgr.vbs /ipk xxxxx-xxxxx-xxxxx-xxxxx-xxxxx
if /i %sku%==homebasic cscript %windir%\system32\slmgr.vbs /ipk xxxxx-xxxxx-xxxxx-xxxxx-xxxxx
if /i %sku%==homepremium cscript %windir%\system32\slmgr.vbs /ipk xxxxx-xxxxx-xxxxx-xxxxx-xxxxx
if /i %sku%==professional cscript %windir%\system32\slmgr.vbs /ipk xxxxx-xxxxx-xxxxx-xxxxx-xxxxx
if /i %sku%==ultimate cscript %windir%\system32\slmgr.vbs /ipk xxxxx-xxxxx-xxxxx-xxxxx-xxxxx
제가 활용하는 수준은 딱 이정도이고 나머지 FOR 옵션에 대해서는 잘 모르겠습니다. 그냥 한번 읽어봤을 때 웬지 제가 사용할 일이 없을 것 같은 옵션들은 이해하려는 노력을 하지 않게 되더군요. 그리고 이 FOR 구문은 그 자체보다 괄호 안에, DO 뒤에 무엇을 넣어주느냐에 따라 가치가 결정된다고 생각합니다. 보통 IF와 SET 구문을 곁들여서 활용하니 IF와 SET에 대해서도 사용법을 익혀두시면 좋을 것 같습니다.