L-Samuels
L-Samuels

Reputation: 2832

Escaping whitespace in String variable

@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
        )
      )
    )

So i have the above batch script. The problem is when i print out the value of CURRENT_CHECKSUM the file directory is truncated and instead of echoing

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

I instead get

c:\documents

output to the fciv call returns

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

Upvotes: 0

Views: 87

Answers (3)

double-beep
double-beep

Reputation: 5519

There are several solutions to this, but I will show you now the most general one, which works if you actually want to remove the first token:

@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%

A shorter, but not so general solution, would be:

@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%

It is also possible to replace the last for /F loop with the following one and with the same about meaning:

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%

which does exactly the same (difference with previous is 1 byte :)).

Upvotes: 0

aschipfl
aschipfl

Reputation: 34989

Actually I cannot reproduce the output you described, because I get the (quoted) checksum of the file when echoing !CURRENT_CHECKSUM!, but not the partial file path as you describe.

Anyway, I believe you defined the for /F options wrongly; you need something like tokens=1*, so you will get two tokens, which are separated by the first (sequence of) whitespace(s), and the second token may even contain whitespaces on its own. By the way, there is no need to use two for /F loops, one is enough.

So here is my suggestion of the fixed code:

@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

This is what I did:

  • one for /F loop with the proper options applied;
  • used the quoted set syntax (the quotes protect special characters but are not part of the values);
  • quoted both comparison expressions to avoid problems in case they are empty;
  • applied delayed expansion also on !DATE! and !TIME!;
  • removed interim variables and used for /F variables immediately;
  • replaced (commented out) exit by exit /B to quit the batch file but not the parent cmd instance;
  • removed call to run fciv.exe as it is not a batch file but an executable;

Upvotes: 2

Recigio Poffo
Recigio Poffo

Reputation: 61

Try setting with "":

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

Upvotes: 0

Related Questions