在String变量中转义空格

时间:2019-02-05 16:08:49

标签: batch-file

@echo off
setlocal enableextensions enabledelayedexpansion

set CHECKSUM_TOOL=fciv.exe
set DESTINATION_DIR=C:\Documents and Settings\Users\Desktop\testfolder
set CHECKSUM=12345
set APP_NAME=price
set VERIFY_FILE=testfile.txt

for /f "tokens=1" %%m in ('call "%CHECKSUM_TOOL%" -md5 
"%DESTINATION_DIR%\!VERIFY_FILE!"') do (
      for /f "tokens=1 delims=/ " %%n in ("%%m") do (
        set CURRENT_CHECKSUM="%%n"
        if not !CURRENT_CHECKSUM!==!CHECKSUM! (
          echo %DATE% %TIME% [ERROR] %~nx0: Checksum of existing file !CURRENT_CHECKSUM! does not match manifest !CHECKSUM! for %APP_NAME%
          REM exit 1
        )
      )
    )

所以我有上面的批处理脚本。问题是当我打印出CURRENT_CHECKSUM的值时,文件目录被截断了,而不是回显了

C:\Documents and Settings\Users\Desktop\testfolder\testfile.txt

我反而得到

c:\documents

输出到fciv调用返回

bd4e8c3e9b3a880365619e48a779e8e0 c:\documents and settings\Users\desktop\testfolder\testfile.txt 

3 个答案:

答案 0 :(得分:2)

实际上,我无法再现您描述的输出,因为在回显!CURRENT_CHECKSUM!时得到文件的(加引号的)校验和,而不是您描述的部分文件路径。

无论如何,我相信您错误地定义了for /F选项;您需要使用tokens=1*之类的东西,因此您将获得两个令牌,这些令牌由第一个(序列)空格分隔,而第二个令牌甚至可能自己包含空格。顺便说一句,不需要使用两个for /F循环,一个循环就足够了。

这是我对固定代码的建议:

@echo off
setlocal EnableExtensions EnableDelayedExpansion

set "CHECKSUM_TOOL=fciv.exe"
set "DESTINATION_DIR=C:\Documents and Settings\Users\Desktop\testfolder"
set "CHECKSUM=12345"
set "APP_NAME=price"
set "VERIFY_FILE=testfile.txt"

for /F "tokens=1*" %%M in ('
    "%CHECKSUM_TOOL%" -md5 "%DESTINATION_DIR%\%VERIFY_FILE%"
') do if not "%%M"=="%CHECKSUM%" (
    echo !DATE! !TIME! [ERROR] %~nx0: Checksum %%M of existing file %%N does not match manifest %CHECKSUM% for %APP_NAME%
    rem exit /B 1
)

endlocal
exit /B

这就是我所做的:

  • 一个for /F循环,其中应用了适当的选项;
  • 使用引用的set语法(引号保护特殊字符,但不属于值的一部分);
  • 引用两个比较表达式,以避免在它们为空的情况下出现问题;
  • !DATE!!TIME!上也应用了延迟扩展;
  • 删除了临时变量,并立即使用了for /F变量;
  • exit替换(注释掉)exit /B退出批处理文件,但不退出父cmd实例;
  • 删除了call,以运行fciv.exe,因为它不是批处理文件,而是可执行文件;

答案 1 :(得分:0)

尝试使用""进行设置:

set DESTINATION_DIR="C:\Documents and Settings\Users\Desktop\testfolder"

答案 2 :(得分:0)

有多种解决方案,但是现在我将向您展示最通用的解决方案,如果您确实要删除第一个令牌,则可以使用该方法:

@echo off
setlocal EnableDelayedExpansion

set "CHECKSUM_TOOL=fciv.exe"
set "DESTINATION_DIR=C:\Documents and Settings\Users\Desktop\testfolder
set "CHECKSUM=12345"
set "APP_NAME=price"
set "VERIFY_FILE=testfile.txt"

rem Loop to get the first token for substraction later:
for /F "delims=" %%A IN ('call "%CHECKSUM_TOOL%" -md5 "%DESTINATION_DIR%\%VERIFY_FILE%"') do (
    set "output=%%A"
    for /F "tokens=1" %%B IN ("%%A") do (
        set "token_to_substract=%%B"
    )
)
set "expected_output=!output:%token_to_substract% =!"

echo The string you wanted to obtain for a custom reason of yours is: %expected_output%

一个简短但不那么通用的解决方案是:

@echo off

set "CHECKSUM_TOOL=fciv.exe"
set "DESTINATION_DIR=C:\Documents and Settings\Users\Desktop\testfolder
set "CHECKSUM=12345"
set "APP_NAME=price"
set "VERIFY_FILE=testfile.txt"

for /F "tokens=2 delims=:" %%A IN ('call "%CHECKSUM_TOOL%" -md5 "%DESTINATION_DIR%\%VERIFY_FILE%"') do (
    set "expected_output=c:%%A"
)
echo The string you wanted to obtain for a custom reason of yours is: %expected_output%

也可以用以下内容替换最后一个for /F循环,并且含义相同:

for /F "tokens=2 delims=\" %%A IN ('call "%CHECKSUM_TOOL%" -md5 "%DESTINATION_DIR%\%VERIFY_FILE%"') do (
    set "expected_output=c:\%%A"
)
echo The string you wanted to obtain for a custom reason of yours is: %expected_output%

完全相同(与上一个的区别是1个字节 :) )。