Batch file variable with spaces and parentheses

26,226

Solution 1

The problem is the parentheses in variable01's value. Since it's being expanded in an if condition, those parentheses are being interpreted as flow control. Fix by always putting it in double quotes.

set variable01="C:\Program Files (x86)\SomeProgram\Subfolder"
set variable02="${macro}"

set variable01=%variable01:"=%
set variable02=%variable02:"=%

set variable03=""

if "%variable02:~0,1%"=="$" (
   if "%variable01:~0,1%"=="$" (
      set variable03=%variable03:"=%
   ) else (
      call :set3 "%variable01%"
   )
)
goto :eof

REM If it is important to have single quotes instead of double then
REM I found I had to call a subroutine.  Otherwise the set could be
REM left up in the else.
:set3
set variable03=-o '%~1'
goto :eof

Solution 2

As Nate wrote, the problem in this case are the brackets, but the complete code is still unstable.

It's always better to use delayed expansion, as this is safe against any special characters.
And you should use the extended syntax of SET set "variable=content" to enclose the complete expression with quotes, then it's nearly safe, and the quotes are not added to the content.
And you don't need to remove the quotes later.

This should work with any content in var1 and var2

setlocal EnableDelayedExpansion
set "variable01=C:\Program Files (x86)\SomeProgram\Subfolder"
set "variable02=${macro}"

set "variable03="

if "!variable02:~0,1!"=="$" (
   if "!variable01:~0,1!"=="$" (
      rem
   ) else (
      set "variable03=-o '!variable01!'"
   )
)
echo(!variable03!
Share:
26,226
Hoobajoob
Author by

Hoobajoob

Updated on February 26, 2020

Comments

  • Hoobajoob
    Hoobajoob about 4 years

    I've read numerous threads on different approaches to getting the windows batch file parser to properly handle variables that have spaces, parentheses, and other special characters, but none of the recommendations seems to be able to fix the issue I am having.

    Here is the script (prior to trying any workarounds), whose goal is to set a value for variable03 based on the values found for variable01 and variable02:

    set variable01="C:\Program Files (x86)\SomeProgram\Subfolder"
    set variable02="${macro}"
    
    set variable01=%variable01:"=%
    set variable02=%variable02:"=%
    
    set variable03=""
    
    if %variable02:~0,1%==$ (
       if %variable01:~0,1%==$ (
          set variable03=%variable03:"=%
       ) else (
          set variable03=-o '%variable01%'
       )
    )
    

    ...the values of variable01 and variable02 are not known in advance - they are substituted by another program prior to running the script, so the above script is showing an example set of values for variable01 and variable02 after that substitution has been made.

    The error I get when this script runs is:

    \SomeProgram\Subfolder' was unexpected at this time.
    

    ...which corresponds to the last 'set' line in the above script. I assumed that this error was due to the parentheses in the value of variable01.

    If I change that line to this:

    set "variable03=-o '%variable01%'"
    

    ...then I get this error:

    Files was unexpected at this time.
    

    ...which seems to indicate that it is trying to tokenize on the spaces in variable01, and the parser is still not happy.

    If I then add this line at the top of the script:

     setlocal enableextensions enableDelayedExpansion
    

    ...and change %variable01% to !variable01!, I still get the same error.

    Clearly, I do not understand what the batch file parser needs to meet my requirement that the value of variable03 has the following value:

    -o 'C:\Program Files (x86)\SomeProgram\Subfolder'
    

    ...any suggestions?

  • Hoobajoob
    Hoobajoob about 11 years
    Thanks for the response - this still produces the same error, presumably because variable01 is still getting expanded in the context of that else clause. I suppose another option is to revise the subroutine so that it doesn't require a parameter, and create a different subroutine for each combination of variable01 and variable02 that it can take on...
  • Nate Hekman
    Nate Hekman about 11 years
    Are you sure? I get the error with the code in your question, but I do not get it with my code. I just copy-pasted the above into my notepad and tried it to be sure I didn't have a typo.
  • Nate Hekman
    Nate Hekman about 11 years
    Note the double-quotes in the call :set3 line. If you use single-quotes you'll get the error.
  • Hoobajoob
    Hoobajoob about 11 years
    Yes - same error using double quotes. The version I posted is a simplified version of the real thing, though, so it's possible I've got something else gumming up your suggestion - will update if I find a significant difference. Thanks again!
  • Hoobajoob
    Hoobajoob about 11 years
    I can get this to work by adding double-quotes around the use of variable01 in the nested if line (the second line of the if block). That is: if "%variable01:~0,1%"=="$". I think there may not have been a problem with the 'set' line in the first place.
  • Samuel
    Samuel about 9 years
    "And you should use the extended syntax of SET set "variable=content" to enclose the complete expression with quotes, then it's nearly safe...", why is it only nearly safe? In what case would it fail?
  • jeb
    jeb about 9 years
    @Samuel It can be unsafe when the content contains quotes itself, like set "var=She said: "Dog & Cat" to me" But in this case, for only a path it should be safe
  • Twisted Code
    Twisted Code almost 3 years
    thanks & +1 to both asker and answerer. It didn't occur to me that I might need to put quotes around the use of a path even in an echo command, but since that echo was within and if construct, a closing parenthesis was being treated as the end of the block... It's awkward enough that I'm beginning to think it might be time to rewrite my batch as a power shell script...
  • Twisted Code
    Twisted Code almost 3 years
    "it is always better to use delayed expansion" sure, when there is a delayed expansion equivalent of what you want, but what would the delayed expansion equivalent of %~dp0 (no, I'm not missing a %. That's actually how you get that envvar) be? !~dp0 doesn't act like a variable and !~dp0! is an empty string. (I'm trying to compare %CD% with the directory of the batch file that was started to make sure they are the same.)
  • jeb
    jeb almost 3 years
    @TwistedCode But the expansion of %~dp0 is safe, as it can't contain quotes. It's only problematic to expand it while delayed expansion is enabled and the path contains exclamation marks