1

I am getting a weird error in my batch program. I think the problem is in enable delayed expansion, but the fix I apply doesn't work. This is my code:

setlocal ENABLEDELAYEDEXPANSION

for /l %%x in (1, 1, 3) do (
   set ff=Firefox_45_0.0_%%x
   echo %%x
   firefox.exe -CreateProfile "%ff% %homedrive%%homepath%\Desktop\Firefoxes\Profiles\Firefox_45_0.0_%%x"


)

ff doesn't have any value, although I used delayed expansion. What could be the fix?

EDIT: command printed to console (I don't use @echo off)

   C:\Users\Home2\Desktop\Firefoxes\Versions\Firefox_45_0.0>(
set ff=Firefox_45_0.0_1
 echo 1
 firefox.exe -CreateProfile "!ff! C:\Users\Home2\Desktop\Firefoxes\Profiles\Firefox_45_0.0_1"
    )

What is funny is that it actually performs as expected, although it prints !ff! in the console.

potato
  • 4,479
  • 7
  • 42
  • 99
  • 4
    you only *enable* delayed expansion, but don't *use* it. Delayed variables are referenced with `!var!` instead of `%var%`. – Stephan Aug 06 '16 at 16:06
  • using !ff! just prints !ff!. Is it because my command uses quotes? How do you use !! when command requires quotes? – potato Aug 06 '16 at 16:54
  • 1
    using your code, just replacing `%ff%` with `!ff!` works fine for me. If it shows `!ff!` literally, that should be a hint, you didn't `setlocal enabledelayedexpansion`. Check your current code. – Stephan Aug 06 '16 at 16:59
  • I realized that although it prints !ff! to the console, the code behaves as expected. Not sure why. but it Works. – potato Aug 06 '16 at 17:11
  • 1
    `it actually performs as expected, although it prints !ff! in the console.` yeah, I admit that's confusing. Shot into the dark: the command repetition is not yet "runtime", so the delayed expansion did not yet take place. – Stephan Aug 06 '16 at 17:13
  • 2
    Command echoing happens when a line is parsed, so delayed expansion did not yet happen; delayed expansion occurs *afterwards* at run-time; that's why `!ff!` is printed; quotation does not change anything as quote-handling is also done while parsing... – aschipfl Aug 06 '16 at 17:20
  • @aschipfl Thanks for clarifying it out to me. Btw, where did you learn about command prompt in such depth? Any particular book? I would also like to master it. – potato Aug 06 '16 at 18:23
  • 1
    Lots of experimenting... and following this extremely useful post: [How does the Windows Command Interpreter (CMD.EXE) parse scripts?](http://stackoverflow.com/a/4095133) – aschipfl Aug 07 '16 at 10:39
  • on Win 10, I tested doesn't work: `md !ff!` literally made a dir called !ff! and then complained for the rest of the iterations that dir exists. – Zimba Sep 27 '19 at 04:22

2 Answers2

5

!ff! fixes it, as delayed expansion uses exclamation marks instead of percent signs.
Delayed expansion mode doesn't change the percent expansion, it adds a new and better way for expansion.

Delayed expansion is disabled by default.
To enable it in a batch file use

setlocal EnableDelayedExpansion
set "var=Hello world"
echo !var!

Attention:
On the command line the command setlocal EnableDelayedExpansion has no effect at all.
You could enable it by starting a new cmd.exe instance with cmd /v:on

jeb
  • 78,592
  • 17
  • 171
  • 225
1

The delayed expansion did not work on Win 10 I tested, from command line.

SETLOCAL EnableDelayedExpansion
SETLOCAL EnableExtensions

The code below worked (to answer the question), without delayed expansion:

for /l %x in (1, 1, 3) do (
   rem set ff=Firefox_45_0.0_%x
   echo Firefox_45_0.0_%x
   firefox.exe -CreateProfile "Firefox_45_0.0_%x %homedrive%%homepath%\Desktop\Firefoxes\Profiles\Firefox_45_0.0_%x"
)

Win 10 CMD doesn't allow changes to SETLOCAL on command line. OK for batch files:

Delayed environment variable expansion is NOT enabled by default. You can enable or disable delayed environment variable expansion for a particular invocation of CMD.EXE with the /V:ON or /V:OFF switch. You can enable or disable delayed expansion for all invocations of CMD.EXE on a machine and/or user logon session by setting either or both of the following REG_DWORD values in the registry using REGEDIT.EXE:

HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\DelayedExpansion

    and/or

HKEY_CURRENT_USER\Software\Microsoft\Command Processor\DelayedExpansion

to either 0x1 or 0x0. The user specific setting takes precedence over the machine setting. The command line switches take precedence over the registry settings.

In a batch file the SETLOCAL ENABLEDELAYEDEXPANSION or DISABLEDELAYEDEXPANSION arguments takes precedence over the /V:ON or /V:OFF switch. See SETLOCAL /? for details.

If delayed environment variable expansion is enabled, then the exclamation character can be used to substitute the value of an environment variable at execution time.

Zimba
  • 2,854
  • 18
  • 26
  • 3
    DelayedExpansion also works on Win 10, but you tried to use it on the command line. There you can't enable it with `SETLOCAL EnableDelayedExpansion` only with `cmd /v:on` – jeb Sep 27 '19 at 05:37
  • This is not special for Win10, that's the behaviour since WinXP, at least. Normally, you don't want to change the default delayed expansion mode with the registry key, else you get unexpcted behaviour from many batch files, expecting that it's disabled at start – jeb Sep 30 '19 at 05:48
  • I was able to change on command line on XP & 8.1 Dell Laptop. On Surface Pro Win 10 doesn't work on command line; /v switch & registry hack works. – Zimba Nov 05 '19 at 14:18
  • I assume, it's already enabled on your XP and 8.1 system, or try to disable it with `SETLOCAL DisableDelayedExpansion` that should fail also – jeb Nov 05 '19 at 15:36
  • I don't think it was enabled by default. I do remember enabling via `setlocal` before setting variables in !! on command line. I've upgraded since, on Win 10 now, and defaulted with registry, so don't have to enable everytime. – Zimba Nov 06 '19 at 11:14