Thursday, March 6, 2008

Setx Escape Character

I recently found out that there is something rather strange with how setx interprets character you pass to it when setting a variable.  It appears that setx has singled out \" as an escaped character.  So if you want to set variable MYVAR to have the value of My name is "Batcheero", here's how you do it:

setx MYVAR "My name is \"Batcheero\""

This is weird because I don't know of any other Windows commands that does this without specifically saying that it is taking regular expressions (like findstr /R).  And the other weird thing is, \" seems to be the only pair that it escapes.  If you try \' or \n or \\, it treats those verbatim.

The bad thing about this singled out treatment is, you have to be careful not to pass a value that ends with a backslash to setx.  For example, if you have a path of a directory that ends with a backslash, which is quite common, then you are in trouble.

set MYPATH=c:\program files\my app\

setx /M MYPATH "%MYPATH%"

This is going to be fine in the current context, but what gets set in global machine environment is c:\program files\my app" (notice the double quote in the end instead of backslash), which is definitely not what you want.

Just one more thing to worry about in Batch world.  Let me know if you are aware of other commands that has this kind of behavior.

4 comments:

Bob said...

Another escape character issue:
How does one go about escaping the double quotes (") character when trying to use it as a delimeter in a file that needs to be parsed? In the following example what should replace X in order to output the first double quoted string in file?

for /f "tokens=1 delims=X" %%a in (file) do (echo %%a)

Wesley said...

Hey 'mate. I appreciate the time you put into this blog. I recently had to look something up, you showed up on the google results, and damn man -- very helpful! -Wes

blognose said...

Interesting observation.

I found a solution to your problem: Just omit the trailing double quote - it's not required.

--- Warning: from here on this comment becomes pointless crazy rummaging in setx oddities. ;-) ---

When investigating this, I found a new "problem" by accident:
For each double-quote (including escaped ones (\")), backslashes *are* in fact escaped between <the last non-escaped character before the double-quote> and <the double-quote>; so if no last double-quote exists (after the leading one), backslashes are never escaped.
Example:
setx test "\\x\\\\y\\\"a\\z\\\"\\
becomes
test=\\x\\\\y\"a\\z\"\\

In particular,
setx test "\\"
becomes
test=\


If you want to continue this important research, try mixing in some ^" at different positions. Things get really funny there...
I can't be bothered anymore to find any clear rules there as it seems so chaotic.


Conclusion: Just avoid the Microsoft Command Shell where possible and use some real scripting tools, like AutoIt, PowerShell or WSH.
(I wish I could follow that advise myself. I want to make the switch for a long time now, but I seem strangely attached to ol' CMD... x_x
I guess it's because I know it well enough to get some easy stuff done pretty quickly; faster than trying to figure out another scripting environment. But I tend to reach CMD's limits pretty soon and from there on it gets ugly and one can loose a lot of time trying to figure out how to - hackingly - do stuff which is merely a simplest function call in other languages... :-/ )


Best regards!

[Testing done on German Vista Biz SP1.]

miguel_nemesis said...

Hi, i have another issue, the following sample will not change the environment variable:

setx "-Xmns -Utpl" -m

I'm really frustrated. Anyway, posted this to show you my issue.