How to escape variables with parentheses inside if-clause in a batch file?

23,082

Solution 1

You can use two different ways

Use the extended syntax of set with quotes set "var=content" will set var with content, content is quoted so special characters aren't problematic and it uses the content till the last quote (without the quote itself)

@echo off
set a=some value with (parentheses) inside
if 1 == 1 (
    set "PATH=%a%"
)

Use delayed expansion (like the answer of shf301) but also transfer the value to the main scope.

@echo off
setlocal enabledelayedexpansion
set a=some value with (parentheses) inside
if 1 == 1 (
    set "localScope_PATH=!a!"
    rem now transfer it to the global scope
    FOR /F "delims=" %%A in ("!localScope_PATH!") DO (
       endlocal
       set "path=%%A"
    )
)

In this case the extended set-syntax is not necessary, I used it only to avoid hidden spaces at the line end.

EDIT: Can I combine this with setlocal EnableDelayedExpansion and using ! instead of % to lazy evaluate variable's value? When I tried I got )! was unexpected at this time.

You can, but it's contra productive, as

@echo off
Setlocal EnableDelayedExpansion
set a=some value with (parentheses) inside
if 1 == 1 (
    set PATH=!a:^)=^^^)!
    set path
)

Then your path contains carets in front of the ) like C:\programs (x86^)

To understand how expansion works you can read SO:How does the Windows Command Interpreter (CMD.EXE) parse scripts?

EDIT2: More problems with the path (containing quotes)
According to this question there can occour another problem with parenthesis when the path contains quotes.

Sample
path="C:\Program Files (x86)";C:\Program Files (x86)\Skype

This is allowed, even it's not necessary to use quotes here, but this destroys the extended SET syntax, as now set "newPath=%path%" expands to

set "newPath="C:\Program Files (x86)";C:\Program Files (x86)\Skype"

Now at least one parenthesis is not inside quotes and is able to break a command block.

But you can simply remove all quotes from the path variable, as said, quotes aren't necessary here.

set "newPath=%path:"=%"

Solution 2

The ) in %a% is the problem here. You can just do some substitution to escape the ).

@echo off
set a=some value with (parentheses) inside
if 1 == 1 (
    set PATH=%a:)=^)%
)

Solution 3

Using delayed expansion will fix that:

@echo off
setlocal enabledelayedexpansion
set a=some value with (parentheses) inside
if 1 == 1 (
    set PATH=!a!
)

Without delayed expansion the if block (from the if to the ending ), %a% is replaced first and then the block is parsed and run. With delayed expansion !a! isn't expanded after the block parsed. So the parsing logic won't see the ) in a and won't cause it issues.

Solution 4

Brackets and variables are always a pain to mix. Use a subroutine instead.

@Echo Off
Set a=some value with (parentheses) inside
If 1 == 1 Call :SetPath
Echo %Path%
Exit /B

:SetPath
Set "Path=%a%"
SetX "Path" "%a%"
Exit /B

I set the variable twice, once using Set for the current shell session, and one using SetX to set it system-wide for future shell sessions. Remove either if they're unneeded.

Share:
23,082
Piotr Dobrogost
Author by

Piotr Dobrogost

se2021 at p.dobrogost.net

Updated on July 19, 2022

Comments

  • Piotr Dobrogost
    Piotr Dobrogost almost 2 years

    Running this batch file

    @echo off
    set a=some value with (parentheses) inside
    if 1 == 1 (
        set PATH=%a%
    )
    

    gives inside was unexpected at this time. error.

    How to escape a variable to avoid this error?