8

While checking the details of the axis2server.bat file in Axis2 binary distribution I see one of the line containing text something like:

FOR %%c in ("%AXIS2_HOME%\lib\*.jar") DO set AXIS2_CLASS_PATH=!AXIS2_CLASS_PATH!;%%c

What does the part below with 2 exclamation marks mean?

!AXIS2_CLASS_PATH!

Names with in % mean variables, not sure what ! mark mean in a batch file.

2
  • 1
    Because of the way variable expansion works, see robvanderwoude.com/variableexpansion.php
    – Alex K.
    Commented Feb 26, 2014 at 12:39
  • @AlexK. thanks it helped. If you could please add an reply I would like to mark the question as answered.
    – Ayusman
    Commented Feb 26, 2014 at 13:31

3 Answers 3

10

When you enable delayed expansion and change or set a variable within a loop then the !variable! syntax allows you to use the variable within the loop.

A drawback is that ! becomes a poison character for delayed expansion.

1
  • 3
    That answers the question, but could you expand on this a bit? Maybe a simple example? Commented Jan 19, 2017 at 12:54
7

As foxidrive mentioned, this is related to delayed expansion. You can find more information by running help set in a cmd prompt, which has the following explanation:

Finally, support for delayed environment variable expansion has been
added.  This support is always disabled by default, but may be
enabled/disabled via the /V command line switch to CMD.EXE.  See CMD /?

Delayed environment variable expansion is useful for getting around
the limitations of the current expansion which happens when a line
of text is read, not when it is executed.  The following example
demonstrates the problem with immediate variable expansion:

    set VAR=before
    if "%VAR%" == "before" (
        set VAR=after
        if "%VAR%" == "after" @echo If you see this, it worked
    )

would never display the message, since the %VAR% in BOTH IF statements
is substituted when the first IF statement is read, since it logically
includes the body of the IF, which is a compound statement.  So the
IF inside the compound statement is really comparing "before" with
"after" which will never be equal.  Similarly, the following example
will not work as expected:

    set LIST=
    for %i in (*) do set LIST=%LIST% %i
    echo %LIST%

in that it will NOT build up a list of files in the current directory,
but instead will just set the LIST variable to the last file found.
Again, this is because the %LIST% is expanded just once when the
FOR statement is read, and at that time the LIST variable is empty.
So the actual FOR loop we are executing is:

    for %i in (*) do set LIST= %i

which just keeps setting LIST to the last file found.

Delayed environment variable expansion allows you to use a different
character (the exclamation mark) to expand environment variables at
execution time.  If delayed variable expansion is enabled, the above
examples could be written as follows to work as intended:

    set VAR=before
    if "%VAR%" == "before" (
        set VAR=after
        if "!VAR!" == "after" @echo If you see this, it worked
    )

    set LIST=
    for %i in (*) do set LIST=!LIST! %i
    echo %LIST%
1

I wanted to hand over a string containing a "!" as parameter (for imageMagick) and the ! was of course interpreted as syntax which broke my script. The solution was for me, change my string from

"Hello World!" 

to (just added a ^ before the !):

"Hello World^!"

I found this trick by reading here: https://www.robvanderwoude.com/escapechars.php

Not the answer you're looking for? Browse other questions tagged or ask your own question.