CMD 배치 파일에서 "for"는 어떻게 작동합니까?
-
03-07-2019 - |
문제
나는 20 년 동안 수십 개의 언어로 프로그래밍 해 왔지만 아무리 노력해도 Windows CMD Shell Batch 파일에서 "작업"에 대한 방법을 결코 이해할 수 없었습니다. 나는 읽었다
http://www.ss64.com/nt/for.html
그리고 인터넷의 다른 몇 가지 기사는 여전히 혼란스럽고 아무것도 달성 할 수 없습니다.
누구든지 "의"일반적인 방법에 대한 간결한 설명을 할 수 있습니까?
좀 더 구체적인 질문을 위해서는 각 경로를 % 경로 % 변수로 반복 할 수있는 방법은 무엇입니까? 나는 함께 시도했다
rem showpathenv.bat
for /f "delims=;" %%g in ("%PATH%") do echo %%g
그것은 첫 번째 경로만을 보여줄 것입니다. 왜요 ? 내가 뭘 잘못 했어?
해결책
답은 실제로 작동하지 않습니다. 솔루션을 직접 찾을 수있었습니다. 이것은 약간 해킹되지만 나에게 문제를 해결합니다.
echo off
setlocal enableextensions
setlocal enabledelayedexpansion
set MAX_TRIES=100
set P=%PATH%
for /L %%a in (1, 1, %MAX_TRIES%) do (
for /F "delims=;" %%g in ("!P!") do (
echo %%g
set P=!P:%%g;=!
if "!P!" == "%%g" goto :eof
)
)
오 ! 나는 배치 파일 프로그래밍이 싫어 !!
업데이트되었습니다
Mark의 솔루션은 더 간단하지만 공백이 포함 된 경로에서는 작동하지 않습니다. 이것은 Mark의 솔루션의 작은 수정 버전입니다
echo off
setlocal enabledelayedexpansion
set NonBlankPath=%PATH: =#%
set TabbedPath=%NonBlankPath:;= %
for %%g in (%TabbedPath%) do (
set GG=%%g
echo !GG:#= !
)
다른 팁
마크의 아이디어는 좋았지 만 아마도 경로가 그 안에 공간이있는 것을 잊었을 것입니다. 교체 ';' ' ""'를 사용하면 대신 모든 경로를 인용 된 문자열로 자릅니다.
set _path="%PATH:;=" "%"
for %%p in (%_path%) do if not "%%~p"=="" echo %%~p
그래서 여기, 당신은 당신의 길이 표시되어 있습니다.
CMD의 명령은 지루한 학습 곡선을 가지고 있습니다. 특히 변수가 ()의 문장 내에서 반응하는 방식은 ... 변수를 할당 할 수 있지만 사용하지 않는 한 ()의 내에서 다시 읽을 수는 없습니다. " setlocal enabledelayedexpansion "명령문이므로 %% 's 대신 (! _var!) 대신 !!와 함께 변수를 사용합니다.
나는 현재 CMD와 독점적으로 스크립트를 위해 일을 위해이 모든 것을 배워야했다 :)
당신은 올바른 아이디어를 가지고 있지만 for /f
개별 문자열이 아닌 멀티 라인 파일 또는 명령에서 작동하도록 설계되었습니다.
가장 간단한 형태로 for
Perl과 같습니다 for
, 또는 다른 모든 언어 foreach
. 당신은 그것을 토큰 목록으로 전달하고, 매번 같은 명령을 호출하여 그것들을 반복합니다.
for %a in (hello world) do @echo %a
확장은 단지 토큰 목록을 구축하는 자동 방법을 제공합니다. 현재 코드가 아무것도 내놓는 이유는 ';
'기본 끝 (주석) 기호입니다. 하지만 변경하더라도 사용해야합니다. %%g, %%h, %%i, ...
배치 파일을 심각하게 제한하는 개별 토큰에 액세스하려면.
당신이 요구하는 것에 가장 가까운 것은 다음과 같습니다.
set TabbedPath=%PATH:;= %
for %%g in (%TabbedPath%) do echo %%g
그러나 그것은 세미콜론을 포함하는 인용 된 경로에 실패 할 것입니다.
내 경험상 for /l
그리고 for /r
기존 명령을 확장하는 데 좋습니다 for
매우 제한적입니다. 지연된 가변 확장으로 약간 더 강력하고 혼란 스러울 수 있습니다 (cmd /v:on
), 그러나 그것은 파일 이름 목록에만 좋습니다.
문자열 조작을 수행 해야하는 경우 WSH 또는 PowerShell을 사용하는 것이 좋습니다. 글을 쓰려고한다면 whereis
Windows의 경우 시도하십시오 where /?
.
이 스레드처럼 오래된 것과 같이 이것을 던지는 것을 거부 할 수 없었습니다 ... 보통 경로의 각 파일을 통해 필요가 발생할 때, 당신이 정말로 원하는 것은 특정 파일을 찾는 것입니다 ... 그렇다면이 경우입니다. ,이 1 라이너는 파일을 찾는 첫 번째 디렉토리를 뱉어냅니다.
(예 : java.exe를 찾고)
for %%x in (java.exe) do echo %%~dp$PATH:x
나는 이것이 매우 늙었다는 것을 알고있다 ... 그러나 단지 재미를 위해 나는 이것을 시도하기로 결정했다.
@Echo OFF
setlocal
set testpath=%path: =#%
FOR /F "tokens=* delims=;" %%P in ("%testpath%") do call :loop %%P
:loop
if '%1'=='' goto endloop
set testpath=%1
set testpath=%testpath:#= %
echo %testpath%
SHIFT
goto :loop
:endloop
pause
endlocal
exit
이것은 카운트가 필요하지 않으며 끝날 때까지 갈 것입니다. 공백에도 같은 문제가 있었지만 전체 변수를 통해 만들었습니다. 이것의 핵심은 루프 레이블과 SHIFT
기능.
for /f
선 입력 당 반복하므로 프로그램에서 첫 번째 경로 만 출력합니다.
귀하의 프로그램은 % PATH %를 한 줄 입력으로 취급하고 ;
, 첫 번째 결과를 %% g에 넣은 다음 출력 %% g (첫 번째 구분 경로)를 넣으십시오.
FOR
본질적으로 데이터 세트의 "줄"을 반복합니다. 이 경우 경로를 포함하는 한 줄이 있습니다. 그만큼 "delims=;"
반 콜론을 분리하라고 말하고 있습니다. 몸을 바꾸면 echo %%g,%%h,%%i,%%j,%%k
입력을 한 줄로 취급하고 여러 토큰으로 나누고 있음을 알 수 있습니다.
이것은 나를 위해 작동합니다 :
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS
@REM insure path is terminated with a ;
set tpath=%path%;
echo.
:again
@REM This FOR statement grabs the first element in the path
FOR /F "delims=;" %%I IN ("%TPATH%") DO (
echo %%I
@REM remove the current element of the path
set TPATH=!TPATH:%%I;=!
)
@REM loop back if there is more to do.
IF DEFINED TPATH GOTO :again
ENDLOCAL
추가로 사용해야합니다 tokens=1,2,...
옵션의 일부 for
루프가 허용됩니다. 이것은 여기에서 당신이 원하는 것을 할 것입니다.
for /f "tokens=1,2,3,4,5,6,7,8,9,10,11,12 delims=;" %a in ("%PATH%") ^
do ( ^
echo. %b ^
& echo. %a ^
& echo. %c ^
& echo. %d ^
& echo. %e ^
& echo. %f ^
& echo. %g ^
& echo. %h ^
& echo. %i ^
& echo. %j ^
& echo. %k ^
& echo. ^
& echo. ...and now for some more... ^
& echo. ^
& echo. %a ^| %b ___ %c ... %d ^
& dir "%e" ^
& cd "%f" ^
& dir /tw "%g" ^
& echo. "%h %i %j %k" ^
& cacls "%f")
이 예제는 처음 12 개의 토큰 (= %PATH %의 디렉토리) 만 처리합니다. 사용 된 각 토큰의 명시 적 열거를 사용합니다. 토큰 이름은 사례에 민감합니다. %a는 %a와 다릅니다.
공간이있는 경로를 위해 저장하려면 서라운드 모두 이 "%i"와 같은 인용문이있는%x. 나는 내가 토큰을 반향하는 곳에서 여기서하지 않았다.
S.th. 이와 같이:
for /f "tokens=1,3,5,7-26* delims=;" %a in ("%PATH%") ^
do ( ^
echo. %c ^
& echo. %b ^
& echo. %a ^
& echo. %d ^
& echo. %e ^
& echo. %f ^
& echo. %g ^
& echo. %h ^
& echo. %i ^
& echo. %j ^
& echo. %k )
이것은 토큰 2,4,6을 건너 뛰고 작은 바로 가기를 사용합니다 (”7-26
") 나머지의 이름을 지정합니다. 이번에는 %c, %b, %a가 반대 순서로 처리되는 방법과 첫 번째 예제와 비교하여 어떻게 '다른 토큰을'의미하는지에 주목하십시오.
그래서 이것은 확실히 당신이 요청한 간결한 설명이 아닙니다. 그러나 아마도 그 예는 지금 조금 더 잘 분명히하는 데 도움이 될 것입니다 ...
다음은 좋은 가이드입니다.
for /f -loop 명령 : 다른 명령의 결과에 대해.
for -loop 명령 : 모든 옵션 파일, 디렉토리, 목록.
전체 가이드 (Windows XP 명령) :
http://www.ss64.com/nt/index.html
편집하다: 죄송합니다. 링크가 이미 Amazon 링크의 일부로 나타 났기 때문에 링크가 이미 OP에 있음을 알지 못했습니다.
그것은 나를 위해 작동합니다.
for /f "delims=;" %g in ('echo %PATH%') do echo %g%
그것은 나를 위해 작동합니다.
for /f "tokens =* delims =;" %g in ( 'echo %path %') do echo %g %