구관이 명관! Batch File 활용 – Batch File도 반복문을 쓸 수 있다! & 디렉터리 경로 탐색 팁 [수정]

2010.09.07 Update: 아크몬드님의 오픈 캐스트 목록에 이 글이 올라왔습니다. 많은 홍보 부탁드립니다. 🙂



한동안 잊고 있다가 뒤늦게 창고 한구석에서 꺼내는 포스트입니다. (입이 열개라도 할 말이 없군요. ㅋㅋㅋ)


지난번 구관이 명관! ([Software Development/Windows NT Command Interpreter] – 구관이 명관! Batch File 활용 – 배치 파일로 프로그램을 작성하는데에 필요한 기본 사항 살펴보기)시리즈를 마무리하기 위해서 글을 좀 더 써봅니다.


반복문을 사용할 수 있다는 점은 상당히 중요한 부분입니다. 배치 파일의 경우도, 열거할 수 있는 대상이 있고, 이를 정확하게 열거하고 제어할 수 있으려면 반복문이 당연히 필요합니다. 이를 돕는 명령어가 바로 for 문인데 간단히 다음의 예시를 살펴보기로 하겠습니다. 아래는 한데 묶여있지 않고 각각 분리된 build.xml 파일을 한꺼번에 컴파일하기 위한 목적으로 작성된 배치 파일의 예시입니다. W 은행의 전산 시스템을 자동화하기 위하여 1년전 처음 작성하였으며, 최근 C 은행의 닷넷 프레임워크 기반 프로젝트 (이 때는 msbuild를 호출하기 위함이었습니다.) 에서도 비슷한 이유로 재사용한 적이 있는 저만의 snippet입니다. 🙂



@rem Java Source 컴파일 도구
@rem 작성일 – 2010년 8월 14일
@rem 작성자 – 남정현


@rem 명령줄 입력을 숨깁니다.
@echo off


@rem 화면을 초기화합니다.
@cls


@echo Java Source 컴파일 작업 시작
@echo.


@rem /d 스위치는 디렉터리 반복 시 사용합니다.
@rem 배치 파일 내에서 변수 선언을 전달하려면 이스케이프 처리를 해야 합니다.
@rem if 문은 아래 명령과 같이 여러 줄 입력이 가능합니다.
@rem ant 명령이 실패하는 경우 Jakarta Ant Build System이 PATH에 등록되어
@rem 있는 상태인지 확인해야 합니다.


@for /d %%i in (.) do @if exist “%%ibuild.xml”. (
  @echo 처리 중: “%%i”
  @ant -buildfile “%%ibuild.xml”
  @echo.
)

@echo on


위의 부분에서 굵게 표시한 부분이 배치 파일 상에서의 for 문의 사용 예시입니다. 배치 파일 안에서 for 문을 사용하기 때문에 조금 변수명에 이스케이프 처리를 위해서 % 지시자를 한번 더 사용한다는 특이 사항만 제외하면 무난한 문법구조를 나타내고 있습니다.


for 문 바로 뒤에 오는 /d 스위치는 열거할 파일 시스템 대상 객체를 디렉터리만으로 한정하는 것으로 이 스위치를 생략할 경우 파일명이 해당 경로상에 존재할 때 같이 열거됩니다. 그 다음, 변수명, 검색할 객체 이름의 패턴 (DOS 방식이므로 전형적인 와일드 카드 패턴을 따릅니다)과 수행할 명령을 do 지시자 다음에 지정합니다. 배치 파일 안이므로 당연히 여러줄의 명령을 한번에 그룹으로 묶을 수 있습니다. 만약 /d 스위치 대신 /f 스위치를 사용할 경우 파일만이 열거될 수 있습니다. 그 외에 /r 스위치를 사용하여 재귀 탐색을 할 수 있고, /l 스위치를 사용하면 우리가 일반적인 프로그래밍 언어에서 사용하는 인덱스 기반 탐색을 위한 카운트 증감 (증가 및 감소 모두 포함됩니다.)을 수행할 수도 있습니다.



@rem 아래 명령은 시작값 1 부터 종료값 5까지 1씩 더하며 반복됩니다.
@rem C 언어로 번역한다면 for (int i = 1; i <= 5; i += 1) 과 같은 의미입니다.
@for /l %%i in (1,1,5) do @echo %%i


@rem 아래 명령은 시작값 5 부터 종료값 1까지 1씩 빼면서 반복됩니다.
@rem C 언어로 번역한다면 for (int i = 5; i >= 1; i -= 1) 과 같은 의미입니다.
@for /l %%i in (5,-1,1) do @echo %%i


보너스: Unix 및 Linux Build Script에서 흔히 사용하는 Stack 기반 Directory 탐색 구현하기


일반적으로 cd 명령 – 혹은 – chdir 명령은 forward only 탐색으로 드라이브를 바꾸거나, 전혀 다른 위치로 갑자기 이동하게 되는 경우 과거로 되돌아갈 근거가 없습니다. 그리고 DOS 기반의 명령이므로 UNIX와 같은 기능은 제공하지 않을 것이라는 일반적인 선입견까지 더해지면서 이런 기능이 “없는 것”으로 분류되기도 합니다만 실제로는 이런 기능이 NT 인터프리터에 존재합니다.


다음의 명령어를 한 번씩 실행해보면 Stack 기반의 탐색이 어떤 의미를 지니는지 아실 수 있습니다.



@rem 참고로 아래에 기호가 더 붙은 이유는 %systemdrive%가 C: 까지이므로 경로임을 표시하기 위해 를 붙여 C:로 인지시키기 위함이었습니다.
@pushd %systemdrive%
@pushd %windir%
@pushd %programfiles%
@popd
@popd
@popd


현재 위치가 어디이든 관계없이 첫 번째 pushd 명령으로 인해서 %systemdrive% 경로로 이동하고 내부 스택에 주어진 경로가 Push됩니다. 두 번째 pushd 명령으로 %windir%가 그 뒤를 이어서 내부 스택에 Push되며, 마지막으로 %programfiles% 경로가 내부 스택에 Push됩니다. 여기까지는 출력 결과만으로 놓고 보았을 때 cd 명령과 차이가 없어 보입니다. 그러나 popd 명령을 사용하면 차이가 나타납니다.


popd 명령을 처음 실행하면, 가장 마지막에 내부 스택에 들어갔던 %windir%가 Pop되고 현재 디렉터리로 변경됩니다. 그리고 다시 popd 명령을 실행하면 이번엔 %systemdrive%로 현재 디렉터리가 변경됩니다. 그리고 다시 popd 명령을 실행하면 원래 위치로 되돌아가는 것을 볼 수 있습니다.


여기서 중요한 점은, 지금 스택에 집어넣고 빼낸 디렉터리들이 원래 위치했던 디렉터리 기준으로는 제각기 독립적인 노드들이었다는 점이며, 디렉터리를 스택 구조에 넣고 관리할 수 있으므로 배치 파일에서 탐색이 자유로워질 수 있다는 이점을 확인할 수 있습니다.


보너스 2: FOR 문으로 텍스트 검색하기


아래의 명령줄은 정규 표현식을 지원하지는 않지만 GREP이 아쉬운 분들을 위한, 간단히 사용할 수 있는 재귀 검색이 지원되는 파일 검색 도구입니다. (출처: http://kennethhunt.com/archives/000173.html)


문법: for /r “검색할 디렉터리” %v in (.확장자) do find /N /I “검색할 키워드” “%~fv” >> “결과를 저장할 파일 혹은 장치”
예시: for /r “C:Windows” %v in (
.txt) do find /n /i “Windows” “%~fv” >> “%userprofile%result.txt”


마무리


보잘것 없어보이는 수단이지만, 때로는 PowerShell을 검토하는 것보다, VBScript를 검토하는 것보다, 그리고 우리 프로그래머 입장에서는 C++이나 C#을 검토하는 것보다 배치 파일에 기대는 것이 더 편할 수 있습니다. 파리를 잡기 위하여 패트리어트 미사일을 날리지 말고, 가까이 있고 쉽게 사용할 수 있는 도구를 여러분의 친구로 만들기를 바라며 소소하게 써내려간 시리즈를 뒤늦게나마 마무리합니다.


감사합니다. 🙂

댓글 남기기