【问题标题】:Delayed expansion and exclamation marks in strings字符串中的延迟扩展和感叹号
【发布时间】:2017-03-10 08:27:27
【问题描述】:

好的,所以我对批处理脚本还是很陌生,我的代码存在这个问题,我在 for 循环的代码中使用 setlocal enabledelayedexpansion,For 循环遍历特定目录中的文件夹名称,但问题是某些名称可能包含“!”(感叹号),如果是这种情况,它们不会被计入“!文件名!”当代码创建一个新目录时,它不包含“!”。此外,当 xcopy 尝试从原始文件夹复制文件时,找不到该文件夹​​,因为变量“!文件名!”和原文不一样(不带感叹号)。

所以我发现为此我只需要在代码的某些部分添加“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 

调用部分调用另一个小(~5 行)批处理文件,检查 sqlplus 服务器是否存在“!文件名!”有效

编辑:除非有“!”,否则整个代码都可以正常工作并执行应有的操作以某个文件夹的名称。

【问题讨论】:

    标签: batch-file


    【解决方案1】:

    问题是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 一起使用,最好通过引用使用变量,并在您的函数中通过

    set "_filename=!%1!"
    

    这是因为CALL 本身在空格、插入符号等方面存在一些令人讨厌的行为

    【讨论】:

      【解决方案2】:

      如果您在代码块中使用变量(带括号的一系列命令),那么%var% 将产生变量的值最初遇到代码块时(即解析时值)和!var! 变量的值在块期间发生变化(即“运行时”值)。

      如果您 call 一个过程 - 内部或外部,则该过程看到的变量的值是来自父级的运行时值。如果这些值在被调用的过程中发生更改,则应用相同的规则,并将更改的值返回给父过程。

      但是如果您调用setlocal,那么如果您执行endlocal 指令或在@ 的上下文中到达文件结尾,则所做的任何值变化都将恢复为其原始值987654326@.


      好的 - 这就是延迟扩展的工作原理。

      在您的情况下,根本不需要延迟扩展。在主线 (%%O) 的循环中,您可以使用 %%O 代替 !filename!。在: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 
      

      【讨论】:

      • 如果我错了,请纠正我,但你只是告诉我延迟扩展是如何工作的。但对我来说问题是我不能使用包含“!”的变量当我使用延迟扩展时,因为它计算了“!” int 变量作为命令(或者我不知道如何调用它们),但我不知道如何“修复”我的代码,即延迟扩展的东西不计入“!”在变量中作为“它的”命令,但只是作为一个字符
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-14
      • 1970-01-01
      • 1970-01-01
      • 2017-05-21
      • 2018-11-13
      • 1970-01-01
      相关资源
      最近更新 更多