'Failing to match string with disk serial in batch

I've very little experience with batch, and right now I'm having a hard time comparing strings.

Essentially, what I actually want is to check if I have an external drive mounted and if I do trigger a command. I get all the drives serials and check if the one I'm expected is in the list:

:: I've tested with and without the EnableDelayedExpansion:
::setlocal EnableDelayedExpansion  
::setlocal EnableExtensions EnableDelayedExpansion

set torun=wmic diskdrive get serialnumber /format:value
for /f "tokens=2 delims==" %%a in ('%torun%') do (
    ::set "serial=%%a"
    echo %%a
    set "expected=     ABCDEFG1"
    if "!expected!" == "%%a" echo Valid serial number!
)

When I run this, I actually see the drivers serials printed, and the one I want is in the list, but the if statement never triggers and I actually tried several different ways. I've tried:

if %%a == "     ABCDEFG1" echo Valid serial number!
if "%%a" == "     ABCDEFG1" echo Valid serial number!
if /I "!expected!" == "%%a" echo Valid serial number!
if !expected!" == "%%a" echo Valid serial number!
if %expected% == "%%a" echo Valid serial number!
if "%expected%" == "%%a" echo Valid serial number!

And several other variations, sometimes the script run but doesn't trigger the echo Valid serial number!, and othertimes I get echo was unexpected at this time.

It's worth noting that in the echo %%a some drivers come with several trailing spaces before the serial, and I've tried checking with both the spaces and without.

PS.: I've the correct serial in my script.



Solution 1:[1]

I would do it differently:

From the :

%SystemRoot%\System32\wbem\WMIC.exe DiskDrive Where "SerialNumber Like ' %ABCDEFG1'" Assoc /ResultClass:Win32_PnPEntity 2>NUL | %SystemRoot%\System32\findstr.exe "^_" 1>NUL && (Echo Valid serial number) || Echo Invalid serial number

From a :

@%SystemRoot%\System32\wbem\WMIC.exe DiskDrive Where "SerialNumber Like ' %%ABCDEFG1'" Assoc /ResultClass:Win32_PnPEntity 2>NUL | %SystemRoot%\System32\findstr.exe "^_" 1>NUL && (Echo Valid serial number) || Echo Invalid serial number

Alternatively, if you wanted to do it your way, via a for loop, don't use a standard list format, use a managed object format, which will omit any false leading space character(s), and make your comparison much simpler:

@For /F Tokens^=6^ Delims^=^" %%G In ('%SystemRoot%\System32\wbem\WMIC.exe DiskDrive Get SerialNumber /Format:MOF 2^>NUL') Do @Set "DriveSerial=%%G"
@If /I "%DriveSerial%" == "ABCDEFG1" Echo Valid serial number 

As a courtesy, here's an example which more fully matches your submitted methodology:

@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "ExpectedSerial=ABCDEFG1"
Set "ToRun=%SystemRoot%\System32\wbem\WMIC.exe DiskDrive Get SerialNumber"
For /F Tokens^=6^ Delims^=^" %%G In ('%ToRun% /Format:MOF 2^>NUL') Do (
    Echo %%G
    If /I "%ExpectedSerial%" == "%%G" Echo Valid serial number!
    Rem Set "DriveSerial=%%G"
    Rem SetLocal EnableDelayedExpansion
    Rem If /I "%ExpectedSerial%" == "!DriveSerial!" Echo Valid serial number^^!
    Rem EndLocal
)
Pause

You'll note that I have correctly used Rem to comment my code. You should not use a broken label, (::), as a comment, especially when that can often fail within a parenthesized block of code. Please remark and unremark the lines as needed.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1