22

I've got a problem with a batch file (Windows 7 x64). I've managed to reduce it to the following (there are two empty comment lines; it doesn't seem to matter whether there's an actual comment):

@echo off

if /i [%1]==[] (
    echo A
    ::
    ::
    echo B
)

Putting this in a batch file and then running it with no parameters produces the following output:

A
The system cannot find the drive specified.
B

Deleting one of the :: lines, or deleting the surrounding if, fixes things so you get the expected output:

A
B

What's going on here? Why is it looking for a drive?

Edit

Thanks for the responses for far. So my question really boils down to this:

What are the rules for determining whether :: means "start of comment" or "drive letter colon"?

Perhaps it's easier to just switch back to REM for adding comments so there's no scope for ambiguity, but I do find the :: style easier to read.

Matthew Strawbridge
  • 19,940
  • 10
  • 72
  • 93

2 Answers2

28

It's an obscoure effect in batch code blocks.

In a code block a label in one line requires always a secondary line with quite different syntax rules (for a secondary line).
SO: goto command not working

The secondary line must be a command or simple label, but not a parenthesis nor a double colon nor an internal command appended with a parenthesis.

MC ND explained that the : is used here like a normal drive letter, that's really true!
But only in the secondary line and even you can suppress the error by a subst :: C:\, the line is handled like a label (You can't start anything).

subst :: C:\
(
:label
::\windows\system32\calc.exe
)

And the secondary line accepts & even when the line is a label.

Failing samples

(
:Label at the end fails
)

(
:label
  ( 
    echo new Block fails
  )
echo ...
)

(
:label
:: Double colon fails
)

(
:label
echo( fails also, as now a file named "echo(" is searched for execution
)

And now working ones

(
::Works
:with a "normal" label in the second line
)

(
:But this label! & echo This will not echo'd
:but & echo You can see this !
)

(
:label
echo or a simple command works too
)

Sometimes :: is used as a comment style, this can cause problems inside blocks, if you don't care about the secondary line.

Edit: To answer your second question

What are the rules for determining whether :: means "start of comment" or "drive letter colon"?

The first :: is always a comment or label, in the next line it's always a drive letter colon.

jeb
  • 78,592
  • 17
  • 171
  • 225
  • 2
    Right. The error is in the second `::`, and the reason what you stated. First line is a label and second is expected to be a valid command, and as :: can be considered valid, it is executed. And, yes, you can start something using `start ::\windows\system32\calc.exe`. As commented before, not all parts of the system handle it. – MC ND Nov 07 '13 at 22:14
6

:: is a valid drive. Just as c: or d: but the letter is :

So, your lines are trying to change from the current drive to drive ::

Example: try subst :: c:\ and then dir ::\

MC ND
  • 69,615
  • 8
  • 84
  • 126
  • +1, but `::` is not a 'fully satisfying' drive, `subst` without parameters doesn't display this. – Endoro Nov 07 '13 at 19:19
  • @Endoro, `mountvol :: /L` and `mountvol c: /L` . For me both are the same volume. But yes, not all tools in the system work with it. – MC ND Nov 07 '13 at 20:15
  • 1
    But why it works when you insert an `echo x` between the two `::` lines? – jeb Nov 07 '13 at 20:58
  • +1 I've tested it and it really suppress the syntax error in the second line – jeb Nov 07 '13 at 21:44