JHB의 프로그래밍 삽질기

윈도우 배치 파일 강좌 본문

PROGRAMMING/Etc

윈도우 배치 파일 강좌

roter 2018.01.06 12:29

2012년 7월 23일 판올림

2010년 5월 4일 재수정 합니다.

 

 

제목은 거창한데... 사실.. 나도 정확히 모른다.

이글을 보는 사람들은 말할것이다.  처음 보시는 분은 정확한 사용법을 알려준다고 해놓고선 웬

낚시글이나.. 그리고 나를 잘아는 사람들은 아니 댁처럼 잘쓰는 사람이? 모른다고 그러면?

 

사실.. 말해서.. 우리나라 같은경우 쓰는게 다 일룰적이고 알고리즘 적으로 한눈에 보면

아 뭐하는 옵션이다라고 알수있지만.. 사실.. 우리나라에서 한발자국만 나가보면..  기본에서 나오는것을 완전

무시한 for문을 돌리고 있는데도 잘만 먹는 즉 우리에게 아직 혹은 전문적으로 않알려진 숨겨진 방법들이

많지만.. 우리는 그 기본에 기본도 모르고 있다.

 

물론 외국 사이트 가면 알고리즘 적으로 고급적인 for 사용법을 알아 볼러고 맘 먹고 검색을 해도..거의..

국내 수준의 알고리즘 거다가 좀 특이한건 뭐 그리 알고리즘이 복잡해서 알아보기 힘들고..

이런 고급기술도 역시 전문적으로 필요로 하는 사람들도 그냥 기초 단계에서 머무르고

있고.. 거의 사용하지 않는다. 왜? 잘모르니깐..ㅠ_ㅠ;

 

우선 기본 문법..

for /? 처보면

 

for %변수 in (집합) do 명령어

 

이게 맨처음 뜬다. 사실 여기에는 함정이 도사리고 있다.

 

변수 라는것이 보통 배치화일에서는 %변수면% 이렇게 해야 하지만 for 문에서는 기준은 %변수명

이것이다.

 

또한 이 변수명은 a b c d e f g 이런식의 영문자 한자만 써야 한다.

%a %b %c 이런식이다.

 

거기다가 옵션으로 % 이게 붙으무로 사실상 변수는 %%변수명 이것이다.

올바른 방법은

 

for %%i in (집합) do 명령어

이것이라는것이다.

 

실질적으로 for %%i in (*) do 명령어 이명령어를 실행시키면

 

@echo off

for %%i in (*) do echo %%i

 

현재 폴더의 파일 목록을 보여준다.

그럼 우리가 알수 있는것은?

() 이안에는 파일명 처리 해주는것을 알수있다.

 

for %I in ( *.bak *.old *.tmp ) do del %I

이것을 실행 할경우

DEL *.BAK

DEL *.OLD

DEL *.TMP 를 수행할 것 입니다.

 

그다음 for /d %%i in (*) do echo %%i

현재폴더에서 디렉토리 내용을 보여준다.

 

그다음 for /r %%i in (*) do echo %%i

현재폴더에서 모든 화일 출력 

for /r %%i in (.) do echo %%i

현재 폴더에서 폴더를 출력

 

for /L %%A in (1,1,100) do echo %%A

1부터 100까지 출력한다.

for /L %%A in (100,-1,1) do echo %%A

100부터 1까지 거꾸로 출력한다.

 

응용..

for /L %%A in(1,1,3) do MD DIR%%A

이러면 DIR1~3개의 폴더를 생성한다.

 

for /L %%A in(1,1,3) do RD DIR%%A

이러면 DIR1~3의 폴더를 삭제한다.

 

이걸 보면 폴더를 생성하는건 아주 우수은 일이 되어버린다.

 

FOR /F "옵션" %%I IN (집합) DO 명령어

주로 파일 처리때 쓰며, 아마도 배치화일 작성할떄 가장 많이 쓰여진다. 왜?

파일을 읽어 드릴수가 있기 떄문이다.

 

분명 FOR /? 을 해보면 엄청나게 많은 내용을 설명하고 있지만.. 설명이 어러워..

이게 당췌 뭐하는 놈인지 알수가 없다는거다.

 

우선 집합을 살펴보자... 옵션은 4가지가 있다.

 

(파일)

("문자열")

('명령어')

(`문자열`)

이 4가지로 분류가 된다.

 

EOL 행끝 문자열을 지정

FOR /F "eol=S" %%F IN ("SDFDSF_SDFDSF") DO ECHO %%F

 

이게 FOR /? 치면 행끝 문자열 지정이라고 하지만.. 들어보면 행을 끝내주는 것에 대하여 체크를 하는것인지...

아니면 이렇다할 어떤 수식도 없다는것에 대하여.. 참 엿같다. 물론 자세히 읽어보면 설명은 되있지만..

명확하지가 않다라는것이다.

EOL 은 첫글자가 S 로시작하는 모든 데이터를 씹는다라는 거다..

그 뜻이다.

EOL로 등록된 한글자로 시작되는 행은 모두 씹는다라는 뜻이다.

중간이건 뒤에 붙건 암 상관없이..

 

SKIP 설명이다.

FOR /F %%F IN ('DIR') DO ECHO %%F

이 명령어를 처보면.. C,볼륨 C:\ 이런 것이 매위에 있다.. 물론 3라인을 걸처서 말이다.

 

즉 파일이 아닌 DIR 명령어 출력중 내용이라는것을 알수있다. 그다음이 파일 날자이고..

FOR /F "SKIP=4" %%F IN ('DIR') DO ECHO %%F

이렇게 처보면 윗단의 출력 내용들은 삭잘려서 나가게 된다.

물론.. 지금 DIR 을 처서 나왔는데 어다가 써먹을떄가 없다. 왜? 파일명이 아닌 날짜만 주룩 나와서

멀 해먹겠냐?

 

잘 생각해보면.. DIR 에 /B를 치면 화일명만 뽑을수가 있다라는것..

FOR /F "SKIP=4" %%F IN ('DIR /B') DO ECHO %%F

 

그다음 delims 딜마인즈.. 이것 간간히 자주 쓴다.. ㅋㅋ 이게 정말 행끝 처리 문이다.

FOR /F "delims=." %%F IN ('DIR /B') DO ECHO %%F

이러면.. 파일명중 이름 부분만 돌려 준다.

. 이전 것들만 보여준다. 물론 명확히 말해서 폴더량 파일이량 다 보여주는것이지만..

이론상 이렇다는것이다. 물론 폴더만 뽑는다고 해서..

네임 "." 처리 이것으로 폴더명 뽑는것은 아니라는것이다.

 

우리가 예전에는 dir *.  이러면 폴더명이 나왔지만..

요즘은 개념이 없는 파일들이 많아서 확장자 자체가 없는것들이 수두룩 하기 때문에.. 이렇게 뽑으면

난감할수있다. 이것에 대하여서는 나중에 이야기 해본다.

 

그다음 tokens 이것.. 아주 중요하고 아주 많이 써먹고 그러나 현실은 잘모르는..

tokens=x,y,m-n 당췌 이게 무슨 뜻이냐??????????

for /? 이렇게 처보면 알듯 말듯 괴상하게 설명 해놓고.. 이해 불가능할정도로 사람

헷갈리게 만들어 놨다.

 

tokens 는 한마디로 출력시 자릿수를 말하는것이다.

FOR /F "tokens=1" %%F IN ('DIR') DO ECHO %%F

시간

FOR /F "tokens=2" %%F IN ('DIR') DO ECHO %%F

AM/PM 표시

FOR /F "tokens=3" %%F IN ('DIR') DO ECHO %%F

시간

:

:

자리수를 뽑는것이다

그다음..

 

tokens=1,5 는 무슨 뜻이냐? 난 처음에.. 1에서 5까지 출력 해주겠지..

변수에 넣어주는것 아닐까라고 생각했다. 그럼 5개 변수를 써서.. h부터 시작하면 h i j k l 이런형식으 변수가

필요 하는? 떙이다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

 

이건.. 순전히 1번 라인 5번 라인만 뽑겠다라는 것이다.

즉..

 

FOR /F "tokens=1,3,5" %%f IN ('DIR') DO ECHO %%f %%g %%h

이러면 날짜 시간 파일명 이순이다.

아니 토큰에다가 3갤 쓰던 4갤 쓰던.. 자리수 공략한다는것이다.

 

자 그럼.. 또하나 가본다..

 

tokens=1* 이건 무슨뜻이냐?

FOR /F "tokens=1*" %%f IN ('DIR') DO ECHO %%f

이것과

FOR /F "tokens=1*" %%f IN ('DIR') DO ECHO %%f %%g

이것을 비교 해보면 %%f 는 첫번쨰 자리를 가지는 것을 알수있다.

그 뒤의 %%g는 ? 그다음에 들어오는 모든 자리수를 열과 관계 없이 모두 포함 하겠다라는 뜻이다.

FOR /F "tokens=1*" %%f IN ('DIR') DO ECHO %%g

고로 이렇게 내리면 날짜를 빼버리고 그외 것들이 표시 되게 된다.

즉 넘버* 실지로 변수가 2개로 늘어나게 된다. 1은 지정한 자리수에 %%f

 * 은  그다음 영문자 변수에  %%g 에 활당되어진다.

 

자 다음..

FOR /F "tokens=1,3*" %%f IN ('DIR') DO ECHO %%f %%g

이러면 날자와 시간이 나올것이다. 중간 am/pm 은 빠졌다.

 

그럼 첫번째 자리와 3번째 자리를 가지고 그외 변수는 뒤에 모든것을 가진다. 

즉 3* 이후의 변수에 모든 걸 담는다라는 뜻이다.

%%f     %%g    %%h

   1     3       *

이렇게 되는것이다.

 

FOR /F "tokens=1,3*" %%f IN ('DIR') DO ECHO %%f %%g %%h

이걸 실행하게 되면

2번 열만 빼고 모두 출력하게 된다라는 뜻이다.

 

그다음 m-n 이것..-_-)a

 

FOR /F "tokens=3-4*" %%f IN ('DIR') DO ECHO %%f %%g %%h

그냥 * 이것 까지 전부 설명 

* 빼면 활당이 사라진다. 즉 %%h는 없어진다.

3열과 4열은 f와 g에 활당되고 * 그뒤 변수인 h에 활당한다.


여기서 약간 수정 하여..

FOR /F "tokens=2-4*" %%f IN ('DIR') DO ECHO %%f %%g %%h %%i

이러면? 2-4 는 2열 과 3열 4열을 뽑겠다는 이야기다. 그 뒤에 * 는 %%i 에 활당 

2에서 4까지 변수로 지정하고.. 나머지 데이터는 %%i 가 가지겠다는 뜻이다.


 




usebackq

 

 

FOR /F "usebackq" %%f IN ("'DIR'") DO ECHO %%f

FOR /F "usebackq" %%f IN ("DIR") DO ECHO %%f

파일로 인식

 

FOR /F "usebackq" %%f IN (`DIR`) DO ECHO %%f

FOR /F %%f IN ('DIR') DO ECHO %%f

FOR /F "usebackq" %%f IN (`"DIR"`) DO ECHO %%f

dir을 실행 결과 값을 계산

 

FOR /F "usebackq" %%f IN ('"DIR"') DO ECHO %%f

"DIR" 문으로 인식

 

FOR /F "usebackq" %%f IN ('DIR') DO ECHO %%f

FOR /F %%f IN ("DIR") DO ECHO %%f

DIR 문자열로 인식

 

FOR /F "usebackq" %%f IN (`'DIR'`) DO ECHO %%f

 

 

dir 자체를 명령어로 실행하여 그값을 가져 온다.

 

여기까지 해보면 아무 의미가 없어진다.

왜? 이유가 없으니깐...

 

명령어를 구지 이렇게 힘들게 쓸이유가 있을까?

외국에서는 그럴수가 있지만 국내 한글 윈도우즈에서는 상당히 유용한 명령어이다.

 

문제는 dir에서 국한 된다면 상당히 별문제가 없지만.. 종종 소스를 짜다보면 생기는 문제들이 있다.

공백이 들어있는 파일경로라든가? 명령어 안에 "" 를 선언하는경우..

 

ipconfig|find /c "192.169.1.1" 이런 구문이라든가..

find /c "1234" dd.txt 라든가..

dir c:\temp\12313 1313 1231313\

종종 우리는 이러한 문제에 봉착하게 된다.

 

for 문 in 에 들어가게 되면 어떻게 될까? 명령어 인식을 하기 위하여..

'dir "c:\temp\1231 1231 131231\"'

이러면 될까?

 

'ipconfig^|find /c "192.169.1.1"'

이렇게 하면 될까?

 

물론 될수도 하지만...usebackq 를 쓰게 된다면.. 이런 기교가 필요가 없어진다.

 

FOR /F "usebackq" %%f IN ('find /c "1234" dd.txt') DO ECHO %%f

FOR /F "usebackq" %%f IN ('dir "c:\temp\12313 1313 1231313\') DO ECHO %%f

이런식으로 처리하면 되니깐.. '' 로 명령어를 정하고 "" 을 써야할경우..

일반적으로 아무것도 없을시 파일로

"" 문자열

'' 명령어 로 처리하지만..usebackq로 쓰게 되면..

``(1자 옆에) 문자열

'' 명령어

"" 파일 집합 으로 처리하게 된다.

즉 파일명이..

 

우리 나라 좋은 나라.txt 라면?

 

for /f "delims=" %%f in (우리 나라 좋은 나라.txt) do echo %%f

100% 에러 난다는거다.


for /f "delims=" %%f in ("우리 나라 좋은 나라.txt") do echo %%f

이건 그냥 문자열 우리 나라 좋은 나라.txt 4개 토큰으로 잘라저 %%f 문자열 토큰으로 처리하게 된다.


for /f "delims=" %%f in ('우리 나라 좋은 나라.txt') do echo %%f

이럴경우 그딴 명령어가 없다고 나올것이고...

 

for /f "usebackq delims=" %%f in ("우리 나라 좋은 나라.txt") do echo %%f

이렇게 하면 인제 정상적으로 파일을 인식하여, 불러오게 된다.

결론은 우리나라 환경에서는 usebackq 를 소스를 짤때 반드시 넣어주는걸 추천한다.

 

 

 

 

 

인제 정규식이다. 정규식 만큼 정말 for 을 다중 for을 그냥 한큐로 만들수있는 귀중한 내용이다.

%~i 따옴표를 제거 해준다. 즉 알맹이로 만들어 준다는건데..

주로 윈도우에서 공간이 들어간 파일명에 대하여 "" 처 줘야 하는데.. 이것이 배치화일에 들어가면

상당히 까다롭게 굴때가 많다. 특히 만약 for문에 들어가게 되면.. "xxxxxx" 화일이 아닌 명령어로 들어가게 되어버린다.

 

FOR %%f IN ("asdasd" "adasd" "ada" "adada") DO echo %%f - %%~f

ex 만들기 더럽게 힘드넹..-_-)a 따옴표가 제거된 것이 출력된다. 써먹을때는?

파일 리다이렉션 할때 즉 파일에 글쓰기 할때 "" 제거 하기 위해서 쓴다.

자주 쓰고 많이 쓰고 유용하게 쓴다. 반드시 기억 하자.. 매우 중요한 정규식이다.

 

 

인제부터는 설명하러면 dir의 거의 신기에 가까운 수준으로 작업 해야한다.ㅠ_ㅠ;;;

%~fi

FOR /f %%g IN ('dir /a-d /b') DO echo "%%~fg"

 

dir /a-d/b 이러면 폴더 제외하고 파일만 뽑아온다.

( 아 정말 옛날 같았으면.. 파일명 뽑아오는데 폴더 제거하는데.. 거의 몇십줄의 코딩을.. ㅋㅋㅋㅋㅋ)

그럼 FI 옵션을 붙이면 어떻게 되냐?

해당 파일을 찾아보고 있으면 해당 파일에 대하여 전체 경로를 부여 해서 출력 해준다.

어떻게?

C:\AUTOEXEC.BAT 이런식으로..

DIR /B를 붙이면 그냥 AUTOEXEC.BAT 가 나오지만..

FI 옵션이 붙게되면 전체 경로를 표시하여 출력 해준다.

 

그다음 %~di 골빼먹는 옵션인데..

해당 파일의 드라이브명을 돌려준다.

FOR /f %%g IN ('dir /a-d /b') DO echo "%%~dg"

c: 이런식으로 해당 파일의 드라이브를 돌려줌..

보통 현재 실행하고 있는 파일 경로를 찾을때 도움이 될듯 싶은데..

더간단한게 있지요..

%cd% 이래버리면.. -_- 현재 폴더명 반환..되기 때문에..그닥.. 않쓰는..

 

pi 드라이브 뺴고 파일명 빼고 확장.. 골아파.. 경로만 쓰일 일이 거의 만무하기 때문에.. 혼자 쓰여지진 않을꺼다.

FOR /f %%g IN ('dir /a-d /b') DO echo "%%~pg"

 

ni 확장자 뛰고 순수 파일명만..

FOR /f %%g IN ('dir /a-d /b') DO echo "%%~ng"

 

xi 파일명 뛰고 확장자만

FOR /f %%g IN ('dir /a-d /b') DO echo "%%~xg"

 

si

FOR /f %%g IN ('dir /ad /b /s') DO echo "%%~sg"

이러면 8.3 경로로 폴더를 보여줄것이다. 물론 파일명이 긴것이 있으면 쓰면 좋지만..

-_- 나는 루트에 긴파일명이 없기때문에 폴더를 열어 본것이다.

 

ai

FOR /f %%g IN ('dir /a-d /b') DO echo "%%~ag"

FOR /f %%g IN ('dir /ad /b /s') DO echo "%%~ag"

파일 속성이나 폴더 속성을 알수가 있다. 구지 attrib 를 그냥 실행 시켰을때량 비슷한 속성값을 알려주는..

 

ti

FOR /f %%g IN ('dir /a-d /b') DO echo "%%~tg"

파일의 날짜와 시간으로만 확장 차라리 그냥 dir 해서 토큰으로 처리하는게..--)a 물론 잡다한것 안나온다는게.. 매리트가 큰..

 

zi

FOR /f %%g IN ('dir /a-d /b') DO echo "%%~zg"

용량으로 확장 시켜줌..

 

path는 안써봤으므로.. 캔슬..하고 싶으나..

 

-_-)a 패스는 어케 쓰는지 나도 모름..윈도우에서 path를 쓸일이 있어야지..ㅠ_ㅠ;

일단 나왔으니..강제로 설명을..

아주 쩌는 명령어..

path=%path%;c:\
FOR /f %%g IN ('dir /a-d /b') DO echo %%g---"%%~dp$path:g"

 

패스를 c:\ 를 걸어주니. 이파일의 실행경로명이 나오는데?

이걸 보니..-_-)a 잼난게 생각이 났는데...

ㅋㅋㅋ 아놔 나 왜이렇케 잔인한지..ㅋㅋ

 

@echo off
setlocal
set dd=c:\tt\
FOR /f %%g IN ('dir /a-d /b') DO echo %%g---"%%~$dd:g"
endlocal

 

(일단 실행에 앞서 tt 폴더를 c:\tt\를 만들어주고 c:\에 있는 몇몇 파일을 tt로 복사한다.)

 

tt폴더와 현재폴더 사이에 같은 파일이 있는지 없는지 찾는..ㄷㄷㄷㄷㄷㄷ 벌써 파일 서츠 엔진이? -_-)a

고로 path 만 들어간다는 이야기가 아니라는 이야기란 잡설..

이게 dir 이라서 그렇치 다른 변수값 응용하면 무궁 무진한..ㅠ_ㅠ 처리가 될듯 싶은데..

 

기타 예제

그대들의 허접한 능력을 한단계 더 발전시킬수 있는 for 예제들..

 

for /r "C:\" %%f in ("*.TXT") do call :NameSizeToTemp "%%~ff"

for /f "delims=" %%a in ('sort /r "%temp%\temp.dir"') do (

for /f "tokens=1-3 delims=./-" %%a in ("%date%") do ( <--- 질문에 있는것이므로 틀릴수 있음

for /f "tokens=1-3 delims=./-" %%f in ('date /t') do (

for /f "tokens=*" %%f in (
  'dir "%MyRoot%\*.*" /s /b /-c /a:-d-s-h') do (
  call :ListFileIfSince "%%~ff"
  )

for /f "tokens=*" %%f in (
    'dir "C:\_D\*.*"
    "C:\_E\*.*"
    "C:\_F\*.*"
    "C:\_G\*.*"
    "C:\_H\*.*"
    "C:\_L\*.*"
    /s /b /-c /a:-d-s-h') do (
  call :ListFileIfSince "%%~ff"
  )

for %%f in (c:\mytemp\tmp$$$.vbs c:\mytemp\tmp$$$.cmd) do (

for /f %%d in ('gawk "BEGIN{printf\"%%s\n\",strftime(\"%%A\")}"') do (

for /f "tokens=* skip=1" %%i in ('wmic OS Get LocalDateTime') do (

for /f "tokens=2,5 delims= " %%a in ('echo.^|date') do (

for /f %%a in ('unxdate "+%%Y%%m%%d"') do (

for /f %%a in ('unxdate "+%%H%%M%%S"') do (

for /f %%a in ('unxdate "+%%Y%%m%%d%%H%%M%%S"') do (

for %%f in (*.*) do echo %%~ff

for %%f in (F-PROT.INI
              PS.DAT
              PS.SBK
              RANDSEED.BIN
              "My Scans.lnk"
              Thumbs.db
              ) do if exist "%tempdir_%\%%~f" echo del /p "%tempdir_%\%%~f"


  for %%f in ("%tempdir_%\Copy of *.JPG") do if exist "%%f" echo del /p "%%f"

for %%f in (call del) do %%f "%TEMP%\tmp$$$.cmd"
for %%L in (5 4 3 2 1 0) do if errorlevel==%%L (

 

for /f "tokens=3 delims= " %%p in (
  'mode con: codepage /status ^| find "Code page"') do (
  set store_codepage_=%%p)

 

for %%a in (y n q) do if /i "%ask_%"=="%%a" goto _%%a

 

for /f "tokens=1 delims=:. " %%h in ("%time%") do set hh_=%%h
for /f "tokens=1 delims=:. " %%h in ('time /t') do set hh_=%%h

for /f "tokens=1-4 delims=:. " %%h in ('echo %time_%') do (

for /f "tokens=* delims=" %%f in ('echo %cd%') do (
for /f "tokens=* delims=" %%f in ("%myfile_%") do (
  set myfile_=%%~sf)

for /f "tokens=* delims=" %%r in ('type %1') do (

 for /f "tokens=1*" %%a in ('echo.%*') do set rest_=%%b

 

*주의 레지스터 건드리는 for문으로 사용시 문제가 있으니 잘아시는 분만 하시길
for /f "tokens=2,*" %%a in ('
    reg query "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\"
      ^|findstr "Path"^|findstr "REG_EXPAND_SZ"') do echo %%b 

  for /f "tokens=2 delims=:" %%a in (
    'fsutil volume diskfree %drive_%^|
      findstr /i /c:"Total # of bytes"') do (

 

 

update 2012 07 23 

for limit loop

 

@echo off
for /l %%l in (*) do echo 123
pause 

 

 

for semi colon data tokens

 

@echo off
for %%l in (123;234;567;123;456;666;777;888) do echo %%l
pause 

 

@echo off
for %%l in (123;234;567;123;456;666;777;888;

abc;123;bcd;ddd;eef;hfgd;sad) do echo %%l
pause

 

or

 

@echo off
for %%l in (123;234;567;123;456;666;777;888
abc;123;bcd;ddd;eef;hfgd;sad) do echo %%l
pause 

*different example

for comma data tokens

 

@echo off
for %%l in (123,234,567,123,456,666,777,888
abc,123,bcd,ddd,eef,hfgd,sad) do echo %%l
pause 

 

0 Comments
댓글쓰기 폼