[SOLVED] Error when quotes used in FOR /F statement

Discussion in 'Scripting' started by A-bit_Tinkerer, Mar 8, 2016.

  1. A-bit_Tinkerer

    A-bit_Tinkerer MDL Junior Member

    Mar 24, 2014
    61
    46
    0
    #1 A-bit_Tinkerer, Mar 8, 2016
    Last edited by a moderator: Apr 20, 2017
    I am looking to use an environment variable for the command in a FOR /F ('command') statement.

    Using an Administrator command prompt window:


    Quotes around DISM command in FOR /F statement cause an error:
    Code:
    C:\>for /F %i in ('"%windir%\system32\dism.exe" /English /Get-WimInfo /WimFile:"E:\x64\sources\install.esd" ^| find /C "Index"') do set images=%i
    The filename, directory name, or volume label syntax is incorrect.
    

    No error after quotes around DISM command removed:
    Code:
    C:\>for /F %i in ('%windir%\system32\dism.exe /English /Get-WimInfo /WimFile:"E:\x64\sources\install.esd" ^| find /C "Index"') do set images=%i
    
    
    C:\>set images=2
    
    In a command script, I want to replace %windir%\system32\dism.exe with %DISM_exe%, which could have a path with spaces, so I would need to use quotes like "%DISM_exe%".

    The FOR /F statement is being used to count the number of indexes in an install.esd file a save the the result in the images environment variable.

    Does any on know a solution that allows quotes to be used around the FOR /F command?
     
  2. KNARZ

    KNARZ MDL Addicted

    Oct 9, 2012
    895
    482
    30
    try: for /F "usebackq" %i in ('"%windir%\system32\dism.exe" /English /Get-WimInfo /WimFile:"E:\x64\sources\install.esd" ^| find /C "Index"') do set images=%i
     
  3. A-bit_Tinkerer

    A-bit_Tinkerer MDL Junior Member

    Mar 24, 2014
    61
    46
    0
    #3 A-bit_Tinkerer, Mar 9, 2016
    Last edited by a moderator: Apr 20, 2017
    (OP)
    The suggested line did not actually use back quotes in the FOR /F (`command`). The result is:
    Code:
    C:\>for /F "usebackq" %i in ('"%windir%\system32\dism.exe" /English /Get-WimInfo /WimFile:"E:\x64\sources\install.esd" ^| find /C "Index"') do set images=%i
    
    C:\>set images="C:\Windows\system32\dism.exe"
    
    However, I should have mentioned that I had already tried the "usebackq" option and it does not work either.
    Code:
    C:>for /F "usebackq" %i in (`"%windir%\system32\dism.exe" /English /Get-WimInfo /WimFile:"E:\x64\sources\install.esd" ^| find /C "Index"`) do set images=%i
    The filename, directory name, or volume label syntax is incorrect.
    
    Thanks for taking the time to respond and offer a suggestion.
     
  4. Flipp3r

    Flipp3r MDL Expert

    Feb 11, 2009
    1,965
    908
    60
    #4 Flipp3r, Mar 10, 2016
    Last edited by a moderator: Apr 20, 2017
    What if you add the path to dism 1st like so:
    Code:
    @echo off
    setlocal
    set path=C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\DISM;%path%
    
    for /F %%i in ('dism.exe /English /Get-WimInfo /WimFile:"w10_10586_64.esd" ^| find /C "Index"') do set images=%%i
    echo Images: %images%
    endlocal
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  5. A-bit_Tinkerer

    A-bit_Tinkerer MDL Junior Member

    Mar 24, 2014
    61
    46
    0
    Adding the dism.exe folder to the beginning of the PATH variable does work. Quotes are not needed in the FOR /F ('command').

    Thank you Flipp3r for your solution.
     
  6. KNARZ

    KNARZ MDL Addicted

    Oct 9, 2012
    895
    482
    30
    I don't see any mistake in your original lines, I'm curious why it's not working with full path.
     
  7. wk-952

    wk-952 MDL Member

    Sep 2, 2012
    116
    287
    10
    #7 wk-952, Mar 11, 2016
    Last edited by a moderator: Apr 20, 2017
    To answer this very shortly, it's because the /F form of the for loop invokes a 2nd parsing session
    on the for loop input that works in a different way other than the normal command-line / batch parser.
    This parsing phase removes surrounding double-quote characters.

    I would like to try to explain this weird behavior in details,
    first let's study the behavior of the CMD when we type something that isn't a valid command.

    # Case 1)
    Open CMD and type something like this: C:\
    you'll get this error: (notice the syntax)
    Code:
    'C:\' is not recognized as an internal or external command,
    operable program or batch file.
    
    # Case 2)
    now type: "C:\"
    Code:
    '"C:\"' is not recognized as an internal or external command,
    operable program or batch file.
    
    So generally it is: <Single quote><the command you typed><Single quote> is not recognized...

    Let's go ahead and try this simple for loop, which should execute the command: C:\ (Case 1)
    Code:
    for /f %A in ('C:\') do echo:
    
    output:
    Code:
    'C:\' is not recognized as an internal or external command,
    operable program or batch file.
    
    same as Case 1, and that was expected.

    Now to the funky part!, let's mimic Case 2 but using a for loop:
    Code:
    for /f %A in ('"C:\"') do echo:
    
    output:
    Code:
    'C:\' is not recognized as an internal or external command,
    operable program or batch file.
    
    wait a second, where did the quotes go ?!
    and the simple plain answer to that is that they're removed!

    Let me show you some more weird/funky results, open CMD and try those:
    1)
    Code:
    for /f %A in ('"C:\"__"D:\"') do echo:
    
    output:
    Code:
    'C:\"__"D:\' is not recognized as an internal or external command,
    operable program or batch file.
    
    2)
    Code:
    for /f %A in ('""C:\""') do echo:
    
    output:
    Code:
    '"C:\"' is not recognized as an internal or external command,
    operable program or batch file.
    
    3) Notice that the 1st character is not a double-quote
    Code:
    for /f %A in ('_"C:\"__"D:\"') do echo:
    
    output:
    Code:
    '_"C:\"__"D:\"' is not recognized as an internal or external command,
    operable program or batch file.
    
    4)
    Code:
    for /f %A in ('""c:\""asd') do echo:
    
    output:
    Code:
    '"c:\"asd' is not recognized as an internal or external command,
    operable program or batch file.
    
    As a general rule: in the /F form of the for loop, if the first character is a double-quote,
    then this character along with the last double-quote (even if it's not the last char in the command-line)
    are both removed.

    So now you should know the root-cause of the your problem,
    and to solve it simply add an extra pair of surrounding quotes:
    Code:
    for /F %i in ('""%windir%\system32\dism.exe" /English /Get-WimInfo /WimFile:"E:\x64\sources\install.esd" ^| find /C "Index""') do set images=%i
    
    so that this extra useless pair gets removed instead of the original useful one.

    But, we're not finished yet!
    we've now broken the command-line / batch parser,
    watch how the above line will be interpreted: (red colors = literal string = not a command)
    Code:
    for /F %i in ('""%windir%\system32\dism.exe" /English /Get-WimInfo /WimFile:"E:\x64\sources\install.esd" ^| find /C "Index""') do set images=%i
    
    that looks completely wrong as opposed to what we want, isn't it ?
    and the solution is very simple, what caused this mess is the extra quotes pair, so let's make it non-effective.


    The final solution:
    Code:
    for /F %i in ('^""%windir%\system32\dism.exe" /English /Get-WimInfo /WimFile:"E:\x64\sources\install.esd" ^| find /C "Index"^"') do set images=%i
    

    EDIT: here's also a sample from the DISM log: (see how the command-line is correct)
    Code:
    2016-03-11 21:05:06, Info                  DISM   DISM.EXE: <----- Starting Dism.exe session ----->
    2016-03-11 21:05:06, Info                  DISM   DISM.EXE: 
    2016-03-11 21:05:06, Info                  DISM   DISM.EXE: Host machine information: OS Version=6.3.9600, Running architecture=amd64, Number of processors=4
    2016-03-11 21:05:06, Info                  DISM   DISM.EXE: Dism.exe version: 6.3.9600.17031
    2016-03-11 21:05:06, Info                  DISM   DISM.EXE: Executing command line: "C:\Windows\system32\dism.exe"  /English /Get-WimInfo /WimFile:"E:\x64\sources\install.esd"