2013-10-30 2 views
1

현재 항목 목록을 통해 실행되는 루프가있어 디렉토리 (아카이브)에 복사합니다. 그러나 목록의 항목 중 하나 (경로 이름에 전역 변수가 있음)는 문자 그대로 (코드 대신 텍스트로) 해석됩니다. 대개 나는 (^^)을 통해 줄을 벗어나 텍스트 대신 코드로 해석 할 수 있음을 알고 있습니다.하지만 분명히 여기에서 뭔가 잘못하고 있습니다. 왜냐하면 작동하지 않기 때문입니다 ...배치 파일 : For/f 루프에서 리터럴 해석을 방지합니다.

문제가되는 것은 (그 안에 탈출로) my.list :

location\foo^^%date:~0,3%*.zip 

내가 사용하는 코드는 ...

for /f "delims=" %%a in (my.list) do (
    echo "%%a" 
) 

에코의

"location\foo^^%date:~0,3%*.zip" 
대신

location\fooMON*.zip 

어떤 도움의

은 크게 감상 할 수있다.

+0

약'call echo "%% a"'? – npocmaka

답변

4

문자를 이스케이프해야 할 때를 혼동합니다.

일부 문자는 특별한 의미가 있습니다 (설명 할 때 "코드"). 문자를 "코드"대신 리터럴 (텍스트)으로 해석하도록 문자를 이스케이프 할 수있는 경우가 종종 있습니다.

Windows CMD.EXE에서 문자를 이스케이프하는 가장 일반적인 방법은 단일 ^ 문자 앞에 접두사를 붙이는 것입니다. 때로는 문자열이 두 번 구문 분석되며, 이는 지연 확장이 활성화 된 경우 !을 처리 할 때 ^^^ (또는 아마도 ^^)의 이스케이프 시퀀스가 ​​필요할 수 있습니다. 파싱을 더 많이 수행하려면 ^자를 더 필요로합니다. 그것은 빨리 혼란스러워 질 수 있고, 그것에 매달린 연습이 필요합니다.

그러나 상황은 완전히 다릅니다. 즉 탈출하여 해결할 수 없습니다. FOR 변수 내에 "코드"가 있으며 그 코드로 해석되기를 원합니다. 그러나 대신 텍스트로 해석됩니다. 이유를 이해하려면 일괄 처리 구문 분석의 여러 단계가 발생하는 순서를 이해해야합니다. 당신은 How does the Windows Command Interpreter (CMD.EXE) parse scripts?을 참조 할 수 있습니다. 그러나 그것은 소화하는데 시간이 걸리는 꽤 발전된 것들입니다.

다음은 다양한 유형의 확장이 발생할 때 나타나는 조잡한 개요입니다. (참고 -이 단계 번호는 링크 된 대답의 위상 번호와 정확히 일치하지 않음) - %1
2) 일반 변수 확장 - %var%
3) 변수 확장을위한 - %%A

1) 매개 변수 확장 4) 지연 변수 확장 - !var!
5) CALL 확장 - 단계를 반복 1)과 2) CALL이

를 포함하면 당신은 당신의 %date:~0,3% 문자열이 정상 (퍼센트) 확장을 받아야합니다. FOR 루프는 확장하지 않고 텍스트 줄을 축 어적으로 읽습니다. 파서가 처음으로 "코드"를 보게되면 %%a FOR 변수가 확장 될 때 3 단계에서 발생합니다. 이미 너무 늦어서 %date:~0,3%을 원하는 방식으로 확장 할 수 없음을 알 수 있습니다.

두 가지 방법으로 문제를 해결할 수 있습니다. 하지만주의해야 할 점은 이러한 솔루션 각각은 잠재적으로 해결해야 할 새로운 문제를 추가 할 수 있다는 점입니다.

^^은 임베디드 "코드"를 강제 확장하려는 순진한 시도라고 가정합니다. ^^은 목록 파일에서 제거해야합니다.

옵션 1 : CALL

for /f "delims=" %%a in (my.list) do call echo "%%a" 

를 사용하여 일반 확장의 추가 라운드를 추가하지만 지금 당신은 잠재적 인 문제가 당신이 을하지 않는 당신의 목록에서 % 문자가있을 수 있습니다 확장하고 싶습니다. 배치 스크립트 내의 퍼센트는 ^으로 이스케이프 할 수 없습니다. 대신 당신은 %%로 그것을 두배로하여 퍼센트를 벗어납니다. 따라서 목록에 백분율 리터럴이 있으면 두 배로 늘려야합니다.

질문과 함께 게시 된 원래 코드는 훨씬 더 복잡했습니다. %%a을 참조한 IF 문이 포함되었습니다. IF 또는 FOR 명령을 호출 할 수 없습니다. 해결 방법은 서브 루틴을 호출하여 값을 전달하고 복잡한 논리를 서브 루틴에 포함시키는 것입니다.

for /f "delims=" %%a in (my.list) do call :processValue "%%a" >>Logs\xfer.log 
exit /b 

:processValue 
echo Attempting to archive %1... 
if exist "c:\%~1" (
    echo f | xcopy "c:\%%a" "c:\Lucas\archive\%~1" /E /C /H /R /Y 
    if %errorlevel%==0 (
    echo ...%1 added to archive for transfer 
    echo. 
) else (
    echo ERROR: %1 not added to archive 
    echo. 
) 
) else (
    echo ERROR: %1 Not found on client computer 
    echo. 
) 

옵션 2 : 사용

!date:~0,3! 대신 %date:~0,3% 사용하도록 목록을 지연 확장을 활성화하고 변경 확장 지연. 지연된 확장은 FOR 변수 확장 이후에 발생하므로 올바르게 확장됩니다.

setlocal enableDelayedExpansion 
for /f "delims=" %%a in (my.list) do echo "%%a" 

그러나 지금 당신은 당신이 확장되고 싶지 할 목록에 ! 문자가있을 수 있습니다 잠재적 인 문제가있다. ! 리터럴을 ^!으로 이스케이프 처리하여 보존 할 수 있습니다.