title: How to survive "delayed variable expansion" in a Windows batch script
body: <p>This is my script:</p>
  
  <pre><code>@echo off
  setlocal
  
  for /f %%i in ('echo aaa/') do set REPO=%%i
  if "%REPO%"=="" (
    echo No input
  ) else (
    echo %REPO:~-1%
    echo %REPO:~0,-1%
    if %REPO:~-1%==/ set REPO=%REPO:~0,-1%
    echo %REPO%
  )
  
  endlocal
  </code></pre>
  
  <p>Please, observe:</p>
  
  <pre><code>c:\dev\shunra\GlobalLibrary\Server&gt;c:\Utils\hgbackup.cmd
  /
  aaa
  aaa/
  
  c:\dev\shunra\GlobalLibrary\Server&gt;
  </code></pre>
  
  <p>What is going on?</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>Note, that I am assigning to REPO something that evaluates to "aaa", hence I expect it to print "aaa", not "aaa/". It drives me crazy.</p>
  
  <p><strong>EDIT2</strong></p>
  
  <p>Apparently, here is the culprit (from help on the set command):</p>
  
  <pre><code>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%
  </code></pre>
  
  <p>But I tried using the <code>!</code> sign, still it does not work for me. I use get <code>!</code> printed on the screen or the wrong result again.</p>