views:

3266

answers:

4

In a Windows batch file, when you do the following:

set myvar="c:\my music & videos"

the variable myvar is stored with the quotes included. Honestly I find that very stupid. The quotes are just to tell where the string begins and ends, not to be stored as part of the value itself.
How can I prevent this from happening?

Thanks.

A: 

You must have the quotes if the text you are setting includes certain characters, including &. If your text didn't include & then you wouldn't need the quotes.

For example if the text was just "c:\my music" then you could do:

set myvar = c:\my music

But because your text has a & you need the quotes.

Edit:

Or as Dave says in his answer you can escape the problem characters with ^^^, but beware of that approach as & isn't the only character you need to escape. In practice it is far easier to stick with the quotes rather than escaping all the problem characters.

andynormancx
That's not the problem. The problem is that the quotes are stored with the rest of the string as part of the value. That's a problem for string concatenation, string comparison and many other things.
GetFree
Fair enough, but if you go the route of escaping instead then make sure you know all the characters that need to be escaped.
andynormancx
A: 

Try using the escape character '^', e.g.

set myvar=c:\my music ^& videos

You'll have you be careful when you expand myvar because the shell might not treat the & as a literal. If the above doesn't work, try inserting a caret into the string too:

set myvar=c:\my music ^^^& videos
Dave
+3  A: 

Use jscript.

Many moons ago (i.e. about 8 years give or take) I was working on a large C++/VB6 project, and I had various bits of Batch Script to do parts of the build.

Then someone pointed me at the Joel Test, I was particularly enamoured of point 2, and set about bringing all my little build scripts into one single build script . . .

and it nearly broke my heart, getting all those little scripts working together, on different machines, with slightly different setups, ye Gods it was dreadful - particularly setting variables and parameter passing. It was really brittle, the slightest thing would break it and require 30 minutes of tweaking to get going again.

Eventually - I can be stubborn me - I chucked the whole lot in and in about a day re-wrote it all in JavaScript, running it from the command prompt with CScript.

I haven't looked back. Although these days it's MSBuild and Cruise Control, if I need to do something even slightly involved with a batch script, I use jscript.

Binary Worrier
Not really an answer to the question, but since I already have been to the la-la-land of cmd.exe string escaping inside and outside of batch files, I totally agree with you. +1
Tomalak
+8  A: 

It depends on how you want to use the variable. If you just want to use the value of the variable without the quotes you can use either delayed expansion and string substitution, or the for command:

@echo OFF
SETLOCAL enabledelayedexpansion

set myvar="C:\my music & videos"

As andynormancx states, the quotes are needed since the string contains the &. Or you can escape it with the ^, but I think the quotes are a little cleaner.

If you use delayed expansion with string substitution, you get the value of the variable without the quotes:

@echo !myvar:"=!
>>> C:\my music & videos

You can also use the for command:

for /f "tokens=* delims=" %%P in (%myvar%) do (
    @echo %%P
)
>>> C:\my music & videos

However, if you want to use the variable in a command, you must use the quoted value or enclose the value of the variable in quotes:

  1. Using string substitution and delayed expansion to use value of the variable without quotes, but use the variable in a command:

    @echo OFF
    SETLOCAL enabledelayedexpansion
    
    
    set myvar="C:\my music & videos"
    md %myvar%
    @echo !myvar:"=! created.
    
  2. Using the for command to use the value of the variable without quotes, but you'll have to surround the variable with quotes when using it in commands:

    @echo OFF
    set myvar="C:\my music & videos"
    
    
    for /f "tokens=* delims=" %%P in (%myvar%) do (
        md "%%P"
        @echo %%P created.
    )
    

Long story short, there's really no clean way to use a path or filename that contains embedded spaces and/or &s in a batch file.

Patrick Cuff
Good answer. Thanks.
GetFree
Excellent answer . . . but it made my head hurt . . .
Binary Worrier
@Binary Worrier; yeah, batch files tend to do that ;)
Patrick Cuff
You must be some sort of batch file God. Such glorious clever idiocy ;)
andynormancx
No, just a masochist ;)
Patrick Cuff