"@echo off"를 일반적으로 사용하기 2. 모든 파일을 지우기 (주: 사실 del /Q *.* 와 같이 /Q(Quiet) 옵션으로도 가능하지만 이쪽은 필터를 사용하여 입력을 자동화 하는것에 촛점을 맞춘듯 싶다. 3.30 버전에선 안될 수도 있었겠죠) 3. 다중 반복 echo off 4. 디렉토리가 존재하는지 확인하는 방법 5. 프로그램을 현디렉토리나 경로에서 사용할 수 있는지 확인하기 6. 배치파일에서 서브루틴이나 재귀적방법을 사용하기 7. 매개 인수(parameter)를 대문자로 바꾸기. 8. 새로운 디렉토리를 경로에 붙이기 9. 두 파일을 비교하기 10. 빈줄을 쓰기 11. pause를 이용해 메세지를 표시하기 12. for를 이용한 다양한 rename 기술 13. 와일드카드를 확인하기 14. 배치 작업을 중간에 그만두지 못하게 하기 15. autoexec.bat를 중지하고 건너뛰는 것을 방지하기 16. 확장자를 인식하기 17. % 문자 인용부호 %1은 배치파일에 주어진 첫번째 인수를 가르킨다. 이처럼 'echo %1'이라고 하면 첫번째 인수를 표시해 준다. 대신에 %1라는 문자를 표시하고 싶은 경우 어떻게 해야하는가? % 문자는 인용부호처럼 행동한다. 그래서 %%1이라고 쓴 경우 실제로는 "%1"이라고 화면에 표시된다. 아래의 간단한 연습을 실행해보라. 18. 배치의 보조 배치파일을 없애기 19. subst 명령어를 경로에 사용하기 20. 일주일에 한번 실행하기. (요일을 확인하기) 21. 파일이름에 경로가 포함되었는지 확인하기 22. 엔터키를 누르지 않고 시간을 보기 23. 에러레벨 값을 확인하는 다른 방법 24. 배치파일의 출력을 리디렉션(redirection)하기 25. 환경저장 공간이 충분한지 확인하기 26. 드라이브를 사용 못하게 하는 간단한 방법 27. 프린터에 escape 명령어를 보내기 28. 무작위 문자열을 만든는 방법 29. 문자열의 길이를 알아내기 30. MsDos의 버전을 환경변수로 저장하기 [출처] Batch파일 정복|작성자 킥업룹
====================================
화면에 명령어들이 표시되지 않게 echo off 하고, 그 라인도 화면에 표시 되지 않게 하기 위해서 다음과 같이 하면 된다.
@echo off
이 것은 MsDos 3.30 이후 버전에서만 작동한다. 이것을 일반적으로 사용하게 하기 위해서 3.30이상의 MsDos를 사용한다면 autoexec.bat 안에 다음과 같이 적어 놓는다.
set _echo=@
그리고 배치파일에서 다음과 같이 사용한다면 어느 버전의 MsDos버전에서도 작동한다.
%_echo%echo off
=====================
가장 흔하게 질문되는 것(FAQ)중의 하나는 del *.* 을 사용껦 때,"Are you sure (Y/N)?" 라는 확인을 어떻게 하면 나타나지 않게 하는것이다. 다음과 같이 사용한다.
echo y| del *.*
화면에 나타나는 메세지도 보이지 않게 하려면 다음과 같이 한다.
echo y| del *.* > nul
이러한 확인 절차를 표시하지 않게 하는 것은 토론의 여지가 많지만,위와 같이 사용할 수 있다.
============
배치파일에서 다중 루프(반복)를 사용하는 것이 가능하다. 다음의 두배치파일을 생각해 보자. 그리고 test.bat을 불러 실행시켜 보자.
echo off
rem TEST.BAT
for %%f in (a b c d e f) do %comspec% /c test2 %%f
rem TEST2.BAT
for %%g in (1 2 3) do echo %1%%g
아니면 한줄로 다음과 같이 써서 사용할 수도 있다.
for %%f in(a b c d e f) do %comspec% /c for %%g in (1 2 3) do echo %%f%%g
이 두번째 방법의 단점은 echo가 화면에 표시된다는 것이다.
======================================
디렉토리가 있는지 확인하는 것은 가끔 매우 쓸모있는 일이다. %1의 디렉토리가 없다면 다음 확인은 참이 될것이다.
if not exist %1nul if not exiat %1nul echo Directory %1 does not exist
=============================================================
배치 프로그램에서 프로그램을 불러서 사용할때, 그 파일에 대한 경로를 써주지 않았을 경우, 그 프로그램이 현재의 디렉토리나 경로에서 사용가능한지 확인할 때 도움이 될 것이다.
set _found=
if exist %1 set _found=yes
for %%d in (%path%) do if exist %%d%1 set _found=yes
for %%d in (%path%) do if exist %%d%1 set _found=yes
if "%_found%"=="yes" goto _continue
echo %1 is not at path or the current directory
goto _out
:_continue
echo %1 found at path or in the current directory
:_out
==================================================
배치파일 안에서 서브루틴을 사용하는 것은 가능하다. 방법은 서브루틴이 실행된 뒤에 돌아가야할 곳을 가르키는 환경변수(예를들면_return)를 설정하는 것이다. 이런 예는 UNPACK.BAT 이나 BOOT.BAT의:_common 과 :_subru 부분에서 찾아 볼 수 있다.
마찬가지로 재귀적인 사용이 가능하다. ("재귀적인 방법"의 의미는 한 배치파일이 자기 자신을 불러 사용하는 것이다.) 이 예는 SAFEDEL.BAT에서 아래의 행을 따라 찾아 보면 된다.
for %%f in (%1) do call safedel %%f recurse
배치파일의 0번째 인수(%0)는 배치파일 자신을 나타내므로, safedel은 %0으로 대치 되어 사용할 수도 있다.
=========================================
다음은 배치파일에 사용한 인수 %1 를 대문자로 바꾸어 주는 예제이다. 이는 MsDos는 path를 대문자로 바꾼다는 점을 이용한 것이다. 결과는 upcase_에 저장될 것이고, 원래의 경로가 다시 저장될 것이다.
set tmp_=%path%
path=%1
set upcase_=%path%
path=%tmp_%
==================================
자주 필요한 이 기술은 매우 간단하다. 예를 들어 %1를 경로에 덧붙이려면
path=%path%;%1
이라고 하면된다.
이 기술은 배치파일 안에서만 사용할 수 있다. 배치파일 안에서만 환경변수(%path%)를 사용할 수 있기 때문이다. 존재하지 않는 디렉토리를 덧붙이려한다거나 중복해서 경로를 덧붙이는 것을 방지하는 ADDPATH.BAT이라는 배치파일이 있다.
=====================
배치파일에서 두 파일이 같은지 아닌지 확인해 볼 수 있다. 이 기술은 MsDos의 외부 명령어인 fc.exe와 find.exe를 사용한다. (외부 명령어라는 뜻은 MsDos와 같이 있는 프로그램들이다. 대부분의 외부 명
령어용 프로그램들은 c:dos 에 위치한다.)
fc %1 %2 > tmp$$$
type tmp$$$ | find /i "fc: no differences encountered" >diffe$$$
if exist notsame$ del notsame$$$
copy diffe$$$ notsame$ > nul
if not exist notsame$ echo Files %1 and %2 are different
if exist notsame$ echo Files %1 and %2 are identical
if exist tmp$$$ del tmp$$$
if exist notsame$ del notsame$
if exist diffe$$$ del diffe$$$
좀더 생각하면 이 기술은 다른 목적에도 사용할 수 있다. 이는 파일안에 주어진 문자열이 있는지 확인 하는데 바탕을 두고 있기 때문이다.
===============
이는 간단하지만 종종 필요하고 유용한 기술이다. echo 바로 다음에점(.)을 찍으면 빈줄을 표시할 수 있다.
echo.
====================================
메세지를 손쉽게 나타나게 할 수 있다. 메세지를 echo한 다음 pause 를 사용하는데, pause의 메세지를 nul로 보내면 된다.
echo Break to quit, any other key to remove the tmp directory
pause > nul
===================================
이 기술이 기본적이고 사소하지만, 이를 생각해 내기란 쉽지 않을 것이다. for 문은 파일의 이름을 바꾸는데 특별히 유용하다. 예를 들면, 내가 다음의 파일들을 가지고 있을 때, (터보 파스칼 TP 4.0,
5.0, 5.5, 6.0) 내가 버전 29를 30으로 바꾸기 원한다고 할때,
tspa2940.zip
tspa2950.zip
tspa2955.zip
tspa2960.zip
다음은 손쉽게 그런 일을 해준다.
for %f in (40 50 55 60) do re tspa29%f.zip tspa30%f.zip
물론 파일이름 바꾸는 일 말고도 이 기술로 다양한 일을 할 수 있다.
하나의 예는 다음과 같다.
for %d in (a b) do format %d:
=========================
이 예제는 인수 %1이 와일드 카드를 사용하고 있는지 아닌지 확인한다.
@echo off
for %%f in (%1) do if "%%f"=="%1" goto _nowilds
echo Parameter %1 contains wildcards (or is missing)
:_nowilds
===========================================
ctty 명령어를 사용해서 입력장치나 출력장치를 새로 설정하여 배치파일을 중단시키는 것을 방지할 수 있다. 여기의 예제는 패스워드로 e를 넣어야 하는 간단한 배치파일이다.
ctty가 nul로 돌려진 동안<,>의 리디렉션이 필요한 것을 눈여겨 보라. ask라는 배치파일을 돕
기 위한 프로그램은 같이 포함되어 있다. ( MsDos의 choice와 비슷하다. 단, 에러 레벨을 입력한 문자의 아스키 값으로 돌리는 것만 틀리다.)
@echo off
ctty nul
echo Now you cannot break the batch with ^C or ^Break > con
:_ask
echo Use e to break > con
ask /b /d < con
if errorlevel==101 if not errorlevel==102 goto _out
goto _ask
:_out
ctty con
echo Back to normal. Now you can break the batch with ^C or
^Break.
이 배치파일이 작동되고 있는 동안에는 alt-crtl-del로 다시 부팅할수도 없다. 이 같은 일을 하는 noboot.exe라는 램상주 프로그램도 있다.
==================================================
브레이크를 눌러 autoexec.bat를 건너 뛰어 지나치지 않게 하기 위해서 다음과 같이 config.sys에 쓰면 된다.
shell=c:command.com /p nul
이렇게 하기 전에 만일의 경우를 대비해서 플로피 디스켓으로 부팅할준비를 해둔다. autoexec.bat 맨 뒷줄에 'ctty con'이라고 덧 붙여야 된다. 그렇게 하지 않으면 키보드가 말을 듣지 않을 것이고, 준비한 플로피 디스켓으로 부팅해야 할 것이다 :-).
=====================
단지 확장자를 확인하려던가, 주어진 파일의 이름에서 확장자를 환경변수로 저장하려고 할때, 이 것은 매우 유용하다. 어떻게 하는지 여기에 있다. 이 배치파일은 PC-Magazine July 1992, Vol 11, No. 13,
page 528에 나온 정보를 이용한 것이다. for 루프에서 슬레시(/)로 시작하는 인수는 두 부분으로 나누어지는데, 처음 부분은 인수의 첫문자이고 다른 부분은 나머지 문자열이다.
이 해결방법에서 하나의 문제점은 .* 이라던가 .??? 이란 확장자를 인식하지 못하는 것이다. 그러나 "와일드카드를 확인하기"를 이용해서 확인하면 될 것이다. 이러한 기술을 이용한 것중에 UNPACK.BAT라
는 배치파일이 있다.
@echo off
set exten_=%1
:_next
set prev_=%exten_%
for %%f in (/%exten_%) do set exten_=%%f
if ".%exten_%"=="%prev_%" goto _extfound
if not "%exten_%"=="%prev_%" goto _next
goto _noext
:_extfound
echo The filename %1 has an extension %exten_%
goto _out
:_noext
echo The filename %1 has no extension
:_out
set exten_=
set prev_=
===================
@echo off
if "%1"=="" goto _out
echo %1
echo %%1
:_out
이 기능을 이용한 것은 "배치의 보조 배치파일을 없애기"를 보아라.
좋은 예로는 DELPATH.BAT가 있다.
=================================
많은 배치 프로그램이 call을 사용해서 보조 배치파일을 불러다 쓴다. 많은 경우 이런 일을 재귀적인 사용을 통해 자기 자신을 불러다씀으로써 보조 파일을 사용하는 것을 줄일 수 있다. 보조코드는 배치파일 자기자신에 넣어 놓는다. 이러한 기술은 와일드 카드를 받아들이는 TYPE 같은 SHOW.BAT 에서 가장 잘 나타나 있다. 일반적으로는 개개의 파일을 type하기 위해서 보조파일이 필요하다. 다른 예는
SAFEDEL.BAT에서 찾아볼수있다.
이와 같은 일을 하기 위한 다른 기술이 있다. 원래의 배치파일이 보조 배치파일을 만든 다음 그것을 불러 사용하는 것이다. 이런 것으로는 DELPATH.BAT의 예를 들 수 있다. 여기에는 사용되는 드라이브를
보여주는 간단한 예가 있다. (c 부터 t 까지 가능하다. 여기선 더 쓰면 줄이 넘어가니까!)
@echo off
echo @echo off> tmp$$$.bat
echo if exist %%1:nul echo Drive %%1: is present>> tmp$$$.bat
for %%d in (c d e f g h i j k l m n o p q r s t) do call tmp$$$
%%d
del tmp$$$.bat
디스크의 볼륨 레이블을 찾아내는 창의적인 기교가 PC-Magazine August 1992, Vol. 11, No. 14, p. 527에 실렸다. 여기는 같은 기술을 사용하는 예가 있다. 환경변수 getdir_에 현재의 디렉토리를 저장한다. 이 기술은 PUSHDIRE.BAT에 사용되고 있다.
@echo off
echo @echo off> director.bat
echo set getdir_=%%2>> director.bat
echo echo %%getdir_%%>> director.bat
dir | find "Directory"> go.bat
call go
if exist director.bat del director.bat
if exist go.bat del go.bat
==================================
어떤 디렉토리를 읽기 쉽게 하기 위해서 간단한 배치파일을 사용한다. 만약 subst 가 이미 설정되어서 생길 수 있는 에러를 방지한다. 그리고 마지막으로 현재 대치된 디렉토리의 현황을 보여준다.
@echo off
if exist m:nul echo The substitution has already been made
if not exist m:nul subst m: c:math
if not exist s:nul subst s: c:support
subst
=============================================
요일을 환경변수에 넣는 것은 어려운 기술이다. 완전한 예는 WEEKLY.BAT에서 찾아볼수 있다. 이 기술의 핵심은 아래에 나와 있는데, 요일을 weekday_라는 환경변수에 저장하는 것이다. 일반 도스 프로그램 외에 아무런 보조 프로그램이 필요없다.
@echo off
echo.| date | find "Current" > tmp$$$.bat
echo set weekday_=%%3> current.bat
call tmp$$$
echo %weekday_%
if "%weekday_%"=="Fri" echo Thank God it's Friday
if exist tmp$$$.bat del tmp$$$.bat
if exist current.bat del current.bat
set weekday_=
사실, 위에서 %%3 대신에 %%4를 사용하면 오늘의 날짜를 확인할 수 있다.
===========================================
우선 먼저 "확장자를 인식하기"를 보면 같은 아이디어인 것을 알 수 있다. 파일이름이 단순히 go.exe 로 이루어 졌는지, 아니면 경로를 포함해서 r:progsgo.exe와 같이 이루어 졌는지 확인하는 것은 r:progs*.exe와 같이 확장자를 사용했다면 매우 복잡한 일이다. 여기서 어떻게 되는지 설명하였다. 이를 완전히 이해했다면 확실히 배치 파일들에 대해서 이해하기 시작했다고 말할 수 있을 것이다.
@echo off
echo @echo off> tmp$$$.bat
echo set rest_=%%1>> tmp$$$.bat
echo :_next>> tmp$$$.bat
echo set prev_=%%rest_%%>> tmp$$$.bat
echo for %%%%g in (/%%rest_%%) do set rest_=%%%%g>> tmp$$$.bat
echo if ":%%rest_%%"=="%%prev_%%" goto _found>> tmp$$$.bat
echo if "%%rest_%%"=="%%prev_%%" goto _found>> tmp$$$.bat
echo if not "%%rest_%%"=="%%prev_%%" goto _next>> tmp$$$.bat
echo goto _nopath>> tmp$$$.bat
echo :_found>> tmp$$ at
echo set haspath_=yes>> tmp$$$.bat
echo goto _out>> tmp$$$.bat
echo :_nopath>> tmp$$$.bat
echo set haspath_=no>> tmp$$$.bat
echo :_out>> tmp$$$.bat
echo set rest_=>> tmp$$$.bat
echo set prev_=>> tmp$$$.bat
for %%f in (%1) do call tmp$$$ %%f
if "%haspath_%"=="yes" echo Filename %1 includes a path
if "%haspath_%"=="no" echo Filename %1 does not include a path
rem if exist tmp$$$.bat del tmp$$$.bat
set haspath_=
====================================
현재의 시간을 보는 간단한 기술은 다음과 같다.
echo.| time | find /v "new"
시간을 환경변수로 저장하는 방법은 LASTBOOT.BAT을 보아라.
====================================
많은 프로그램과 몇개의 도스명령어들( diskcomp, format, xcopy)은끝날 때 에러 레벨을 발생시킨다. 에러레벨의 누적적인 성질 때문에 에러 레벨을 확인하는 것은 다소 복잡해진다. 그래서 만약 에러레벨이 정확히 2인지 확인하기 위해서는 다음과 같이 한다.
if errorlevel==2 if not errorlevel==3 echo Errorlevel 2
for 명령어를 사용하는 다른 방법으로 다음을 들수 있다.
for %%e in (0 1 2 3 4 5 6 7) do if errorlevel==%%e set
_errlev=%%e
if "%_errlev%"=="2" echo Errorlevel 2
좀 더 일반적으로 다음과 같이 할 수 있다.
for %%e in (0 1 2 3 4 5 6 7) do if errorlevel==%%e set
_errlev=%%e
if "%_errlev%"=="2" echo Errorlevel %_errlev%
복잡한 배치파일에서 편리한 방법은 goto를 사용하는 것이다.
for %%e in (0 1 2) do if errorlevel==%%e goto _label%%e
goto _out
:_label0
echo Errorlevel 0
:_label1
echo Errorlevel 1
:_label2
echo Errorlevel 2
:_out
이 기술을 실제로 사용하는 예는 BOOT.BAT에서 찾아볼수 있다.
===============================================
배치파일 안에서의 출력은 손 쉽게 재 방향전환(redirecion)할 수 있다. 다음과 같은 example.bat 이라는 배치파일을 생각해보자.
@echo This is a redirection test> test
"example"를 실행시키면 아래의 문장을 담은 "test"라는 파일을 생성 할 것이다.
This is a redirection test
이 줄은 eoln(end of line: ascii 13 + 10)을 줄 끝에 포함하고 있다. 리디렉션 기호 '>' 앞에 아무런 공백도 주지 않는 것이 현명할때가 있다.
배치파일이 만드는 출력을 다시 재 방향전환(redirection)하는 것은 다소 복잡하다. 다음과 같은 내용을 지닌 example2.bat을 생각해 보자.
@echo This is another redirection test
실행하면,
example2 > test
출력은 화면에 나오고, 빈 test라는 파일이 생성될 것이다. 출력을 재 방향 전환 시키기 위해서는 다음과 같이 command.com 명령어 해석기를 통해서 배치파일을 실행해야 한다.( command.com은 현디렉토리나 경로에 있어야 한다.)
command /c example2 > test
이와 같이 하면 내용이 "test"라는 파일에 담길 것이다.
=====================================
만약 배치파일이 환경저장 변수를 사용하면, 환경저장 공간이 부족할경우가 있다. 만약 "Out of environment space"라는 메세지를 받는다
면 잘 알려진 방법을 통해서 다음과 같이 config.sys 의 shell을 설정해서 환경저장 공간을 늘릴 수 있다.
shell=c:bincommand.com c:bin /e:1024 /p
이 보다 덜 알려진 기술로는 환경저장 공간이 모자라기 전에 미리 확인해 볼수 있다. 아래의 예는 32바이트의 환경이 남아 있는지 확인한다.
@echo off
set test_=12345678901234567890123456789012
if "%test_%"=="12345678901234567890123456789012" goto _yes
echo Insufficient environment space
goto _out
:_yes
echo Sufficient environment space
set test_=
rem Whatever you wish to do
:_out
===========================================
임시로 드라이브를 사용하지 못하게 하려면, subst명령어를 사용하면 된다. 예는 아래와 같다.
@echo off
md c:none
subst d: c:none
다시 사용하게 하려면,
@echo off
subst d: /d
rd c:none
===================================
여기 정말 사소한 기술이 있다. 명령행에서 곧바로 프린터에게 escape sequence를 보낼 수 없다. 그러나 다음과 같은 배치파일을 이용하면 간단하다.
@echo ESC%1> prn
ESC는 진짜 escape문자로 에디터로 쓰여져야 된다. 이 방법의 한가지 결점은 라인피드를 보내는 것이다.
===============================
UseNet news에서 무작위 문자열을 만드는 방법을 물어보는 사람이 있었다. 대답은 다음과 같다. 이를 확장해서 공부해보기 바란다.
@echo off
echo 10 randomize(val(mid$(time$,7,2))) > tmp.bas
echo 20 open "tmp2.bat" for output as #1 >> tmp.bas
echo 30 x$ = mid$(str$(int(rnd*10000)),2) >> tmp.bas
echo 40 print #1,"@set ramdom_=";x$ >> tmp.bas
echo 50 close #2 >> tmp.bas
echo 60 system >> tmp.bas
gwbasic tmp.bas
call tmp2
del tmp.bas
del tmp2.bat
set
============================
문자열의 길이를 찾아내는 일은 PC Magazine January 26, 1993 issue 에 실렸다. 여기서 제안하는 방법은 PC 메거진의 방법과 근본적으로 같지만, 더 일반적이다.
@echo off
set test_=Testing the lenght of a string
echo %test_% > len$&$&$
dir len$&$&$ | find "LEN$&$&$" > go$$$.bat
echo @echo off> len$&$&$.bat
echo set length_=%% len$&$&$.bat
call go$$$
echo The lenght is %length_% bytes
del len$&$&$
del len$&$&$.bat
del go$$$.bat
======================================
ADJCURS.BAT을 보면 알겠지만, 배치파일로만 버전을 알아낼 수있다.
여기에 다른 방법이 있다.
@echo off
ver > go$$$.bat
echo @echo off> ms-dos.bat
echo set version_=%%2>> ms-dos.bat
call go$$$
echo Your MsDos version is %version_%
del go$$$.bat
del ms-dos.bat