Batch file variable with spaces and parentheses
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!
Hoobajoob
Updated on February 26, 2020Comments
-
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 about 11 yearsThanks 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 about 11 yearsAre 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 about 11 yearsNote the double-quotes in the
call :set3
line. If you use single-quotes you'll get the error. -
Hoobajoob about 11 yearsYes - 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 about 11 yearsI 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 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 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 almost 3 yearsthanks & +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 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 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