0

Linked:

Best free resource for learning advanced batch-file usage?

Dealing with quotes in Windows batch scripts

This appears to be one of those maddening quoting issues. In this example program:

@echo off
set wmicpath=%windir%\System32\wbem\wmic.exe

for /f "usebackq" %%a in (`%wmicpath% COMPUTERSYSTEM GET SystemType ^| findstr /I "x64"`) do (
    echo %%a
)

The program runs just fine. Unless you try to quote the wmicpath. Imagine if you will that it contains a long path name. Then you should quote it. But I cannot quite get it to work. This fails:

for /f "usebackq" %%a in (`"%wmicpath%" COMPUTERSYSTEM GET SystemType ^| findstr /I "x64"`) do (

but this works!:

for /f "usebackq" %%a in (`"%wmicpath%" COMPUTERSYSTEM GET SystemType ^| findstr /I x64`) do (

as does this:

for /f "usebackq" %%a in (`"%wmicpath%" COMPUTERSYSTEM GET SystemType`) do (

There's something really odd about matching quotes in a for command. You can quote a command as long as you don't start quoting elsewhere...

Is it possible? I tried escaping at various points but I'm not sure about the escaping rules when quotes are involved...

Edit: I think this link might be the issue (ie: it's a bug): Pipe in for loop breaks double quoted variables

Community
  • 1
  • 1
carveone
  • 889
  • 9
  • 16

3 Answers3

4
@echo off
    setlocal enableextensions disabledelayedexpansion
    set "wmicpath=%windir%\System32\wbem\wmic.exe"

    for /f "usebackq delims=" %%a in (`
        ^""%wmicpath%" COMPUTERSYSTEM GET SystemType ^| findstr /I "x64"^"
    `) do (
        echo %%a
    )

If you look at the start and end of the inner command, you will see two additional ^" (a escaped double quote). Your problem is that the for command is spawning a separate instance of cmd to handle the inner command, and this separate instance is removing the initial and final double quotes.

Why escaped quotes? To avoid this additional quotes being paired with the double quotes in the command that could lead to some other parsing problems.

You can run cmd /? to obtain the help page (sorry, i have a spanish locale so i will not include the output here). You will see a section about the /C and /K usage explaining quote removal behaviour.

MC ND
  • 69,615
  • 8
  • 84
  • 126
  • Excellent! Thanks. I figured out the ^" myself at about 1am last night but didn't know exactly why or where it was documented (if anywhere!). I thought it was a bug but as you say, it's matching initial and final double quotes. – carveone Nov 14 '16 at 11:49
  • This is a sanity saver. – Tony Nov 14 '18 at 22:37
1

First of all I would change the command, WMIC allows you to use a query language LIKE operator which would in this case remove the need to pipe anything.

@Echo Off
Set "WMIC=%SystemRoot%\System32\Wbem\wmic.exe"
For /F "UseBackQ Skip=1" %%a In (
    `""%WMIC%" ComputerSystem Where "SystemType Like 'x64%%'" Get SystemType"`
) Do For %%b In (%%a) Do Echo=%%b
Timeout -1

Then I may even change the format of the command such that I don't use back quotes.

@Echo Off
Set "WMIC=%SystemRoot%\System32\Wbem\wmic.exe"
For /F "Skip=1" %%a In (
    '""%WMIC%" ComputerSystem Where (SystemType Like "x64%%") Get SystemType"'
) Do For %%b In (%%a) Do Echo=%%b
Timeout -1

Whilst this doesn't directly answer the question in the subject title, it does allow for your particular command to work correctly.

However neither are necessary to your particular command example, because you do not need the for loop to echo that output:

@Echo Off
Set "WMIC=%SystemRoot%\System32\Wbem\wmic.exe"
"%WMIC%" ComputerSystem Get SystemType|Find /I "x64"
Timeout -1

Change Find to FindStr if you feel the need.

Compo
  • 36,585
  • 5
  • 27
  • 39
  • You are right about WMIC. Nicely done. I guess if I do something a particular way, I continue to do it that way even if it's less efficient. I think they call that laziness :-) And you're right about my example but in my actual code I store the output and use it further down. – carveone Nov 14 '16 at 11:47
  • 1
    I accept that you are probably doing that, however, to the best of my knowledge only the following would be ouptput based upon your question's chosen command and find criteria, `x64-based`. For that reason you could just use the latter example with `&&` to set that upon success. `"%WMIC%" ComputerSystem Get SystemType|Find /I "x64">Nul&&(Set var=x64-based)`. – Compo Nov 14 '16 at 12:48
0
>x64.txt ECHO x64

for /f "usebackq" %%a in (`"%wmicpath%" COMPUTERSYSTEM GET SystemType ^| findstr /I /g:x64.txt`) do (

might be a work-around, depending on your actual application and preferences.

Magoo
  • 77,302
  • 8
  • 62
  • 84
  • findstr is pretty flexible in that regard but generally I go out of my to avoid creating external files. – carveone Nov 14 '16 at 11:57