2017-03-10 1 views
3

그래, 아직 배치 스크립팅에 익숙하지 않아 for 루프에 대한 코드에서 setlocal enabledelayedexpansion을 사용하고있는 코드에이 문제가 있습니다. For 루프는 통과합니다 폴더 이름을 특정 디렉토리에 넣지 만 문제는 일부 이름에 "!"(느낌표)가 포함될 수 있으며 "! filename!"에 카운트되지 않는 경우입니다. 코드가 새로운 디렉토리를 생성 할 때 "!"는 포함되지 않습니다. 또한 xcopy가 원래 폴더에서 파일을 복사하려고 시도하면 폴더가 발견되지 않습니다. 변수 "! filename!" 원본과 동일하지 않습니다 (느낌표가 없음).문자열의 확장 및 느낌표 지연

그래서이 코드는 코드의 일부분에만 "setlocal 지연 확장 사용"을 추가하고 다른 기능을 해제해야한다는 것을 알았지 만 올바른 위치를 찾지 못하는 것 같습니다.

코드 :

@ECHO OFF 
setlocal enabledelayedexpansion 

SET Location_Folder=V: 
SET Destination_folder=V:\Nonimportable 

SET Check_file_validation=V:\Nonimportable\result.txt 

SET Excluded_folder=Nonimportable 
set "lineNr=12" 

For /f "tokens=*" %%O in ('dir /b /a:d "%Location_Folder%"') do (
    set filename=%%O 

    call D:\somefolder\otherfolder\batscriptname.bat !filename! 
    set Validation= 

    echo !filename!| FINDSTR /i /c:"%Excluded_folder%" >NUL 
    IF ERRORLEVEL 1 (

     for /F "skip=12 delims=" %%a in (%Check_file_validation%) do if not defined Validation (
       set Validation=%%a 
       call :valid 
     ) 
    ) else (
     echo This folder name is excluded: !filename! 
    ) 
) 
goto Finish 
:valid 

echo !Validation!| FINDSTR /c:"1" >NUL 
    if ERRORLEVEL 1 (

     set Folder_path=%Location_Folder%\!filename! 
     set New_Folder_path=%Destination_folder%\!filename! 

     mkdir "!New_Folder_path!" 

     echo D | xcopy /o /y /q /s /v "!Folder_path!" "!New_Folder_path!" 

     rmdir /s /q "!Folder_path!" 
    ) else (

     echo Folder is valid !filename! 
     goto Finish 
    ) 
:Finish 
exit /b 

콜 부분이 경우 SQLPLUS 서버 점검 또 다른 작은 (~ 5lines) 배치 파일을 호출! "파일 이름을!" 유효합니다

편집 : 전체 코드가 제대로 작동하고 "!" 어떤 폴더의 이름으로.

답변

2

당신은 %var%는 블록이 원래 (즉, 구문 분석 시간 값)가 발생하는 변수 의 가치와 !var! 변수의 값을 산출하는 코드 블록 내에서 (명령의 괄호에 일련의) 변수를 사용하는 경우 은 블록 (즉 "런타임"값) 동안 변경됩니다.

call 절차가 내부 또는 외부 인 경우 프로 시저가 보는 변수의 값은 상위의 런타임 값입니다. 이러한 값이 호출 된 프로 시저 내에서 변경되면 동일한 규칙이 적용되고 변경된 값은 상위 프로 시저에 반환됩니다.

그러나 당신은 endlocal 명령을 실행하거나 setlocal의 컨텍스트 내에서 파일의 마지막에 도달하면 이루어지는 값 - 변동이 원래의 값으로 되돌려 다음 setlocal를 호출하는 경우.


확인 - 지연 확장이 작동하는 방식입니다.

귀하의 경우에는 지연 확장을 할 필요가 전혀 없습니다. 메인 라인의 루프 (%%O)에서 !filename! 대신 %%O을 사용할 수 있습니다. :valid 절차에서 두 개의 set 명령을 코드 블록 외부로 옮길 수 있으며 블록 내에서 값이 변경되는 변수에 액세스 할 필요가 없으므로 !vars!을 사용할 필요가 없습니다.

@ECHO OFF 
setlocal 

SET Location_Folder=V: 
SET Destination_folder=V:\Nonimportable 

SET Check_file_validation=V:\Nonimportable\result.txt 

SET Excluded_folder=Nonimportable 
set "lineNr=12" 

For /f "tokens=*" %%O in ('dir /b /a:d "%Location_Folder%"') do (
    set filename=%%O 

    call D:\somefolder\otherfolder\batscriptname.bat %%O 
    set Validation= 

    echo %%O| FINDSTR /i /c:"%Excluded_folder%" >NUL 
    IF ERRORLEVEL 1 (

     for /F "skip=12 delims=" %%a in (%Check_file_validation%) do if not defined Validation (
       set Validation=%%a 
       call :valid 
     ) 
    ) else (
     echo This folder name is excluded: %%O 
    ) 
) 
goto Finish 
:valid 

set Folder_path=%Location_Folder%\%filename% 
set New_Folder_path=%Destination_folder%\%filename% 
echo %Validation%| FINDSTR /c:"1" >NUL 
    if ERRORLEVEL 1 (
     mkdir "%New_Folder_path%" 
     echo D | xcopy /o /y /q /s /v "%Folder_path%" "%New_Folder_path%" 
     rmdir /s /q "%Folder_path%" 
    ) else (
     echo Folder is valid %filename% 
     rem redundant instruction : goto Finish 
    ) 
:Finish 
exit /b 
+0

수정, 그건

set "_filename=!%1!" 

하여 내용을 더 CALL으로 콘텐츠를 사용 참조와 함수에서 변수를 사용하지 말아야합니다 만약 내가 틀렸다면, 당신은 방금 지연된 확장이 어떻게 작동하는지 알려주고 있습니다. 그러나 문제는 "!"을 포함하는 변수를 사용할 수 없다는 것입니다. 지연 확장을 사용하는 동안 "!" int로 변수를 (또는 어떻게 호출 해야할지 모르겠다),하지만 지연된 확장 기능이 "!"수를 계산하지 못하도록 내 코드를 "고치는"방법을 모른다. "그것의"명령으로 변수에 있지만 문자 그대로 –

2

문제는 set filename=%%O의 매개 변수 확장입니다. 에서 %%O은 여전히 ​​느낌표이지만 지연된 확장을 사용하면 앞머리가 삭제됩니다.
결론은 간단하며 FOR 매개 변수를 확장하면 지연된 확장을 사용하지 않아야합니다.

그러나 지연 확장이 필요할 때도 있습니까?
모드를 전환하기 만하면됩니다.

setlocal DisableDelayedExpansion 
For /f "tokens=*" %%O in ('dir /b /a:d "%Location_Folder%"') do (
    set "filename=%%O" -- Here the DelayedExpansion have to be disabled 
    setlocal EnableDelayedExpansion 

    call D:\somefolder\otherfolder\batscriptname.bat filename 
    set "Validation=" 
    ... 
    endlocal 
) 

는 대신 CALL myBat.bat !filename!CALL myBat.bat filename 내 수정을 참조하십시오. CALL 자체가 공간, 캐럿과 성가신 행동을 가지고 있기 때문에
당신은 등