Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

in a batch file, I'm iterating through a list of unc paths in a file, using pushd to change the context to that location, then executing a command. %CD% gives the location of the previous directory, not the currently pushed directory.

for /f "tokens=*" %%A in (filesharelist.txt) do (
 pushd %%A
 echo CD=%CD% - expecting x:\ or x:\subpath here, but get previous directory
 REM xcopy *.xml %DestinationDirectory% /V /C /Y /Z

How do I get the current directory?

share|improve this question
Does the user context the script runs as have access (share and file permissions) to the UNC resource(s)? If you replace your %CD% line(s) with something like echo test >> test.txt after the pushd, is test.txt created where you expect? What I'm getting at is that %CD% might be working fine, but PushD is failing for some reason. – Ƭᴇcʜιᴇ007 Nov 9 '12 at 17:31
techie007: dead wrong. – Joey Nov 9 '12 at 18:29
@techie007 - yes, pushd is working as expected. I tested with DIR >> log.txt as well as CD >> log.txt. – JJS Nov 10 '12 at 21:23
up vote 5 down vote accepted

%CD% works like it should. Your problem is that it is expanded before your for loop even runs. Use delayed expansion instead:

setlocal enabledelayedexpansion
for /f "tokens=*" %%A in (filesharelist.txt) do (
 pushd %%A
 echo CD=!CD!
 REM xcopy *.xml %DestinationDirectory% /V /C /Y /Z

Variable expansion in cmd is a little counterintuitive. Normal environment variables (of the %foo% form, including pseudo-variables like %date%, %cd%, ...) are expanded when a statement is parsed, not when it's executed. Blocks like the one following the do count as a single statement so every variable in the block is replaced by its value before the for loop even runs. Which means %CD% gets replaced by the value it had before the loop. Unsurprisingly, this is the value before the pushd.

Delayed expansion gets around the issue by expanding variables right before a statement is executed. They need to use the !foo! form for that, though and it has to be explicitly activated with setlocal enabledelayedexpansion or cmd has to be started with cmd /v:on or it has to be enabled in the registry. The safest way is the first because it doesn't depend on any outside configuration or environment.

Bonus quiz: Why does %DestinationDirectory% still work as intended?

share|improve this answer
doh. didn't even think to try delayed expansion. Thanks for the gentle reminder. %DestinationDirectory% works because it's not based on either %%A or anything inside the FOR block. It's defined at the top of the batch file :) – JJS Nov 10 '12 at 21:20
+1, this saved me from pulling out all of my hair today. DOS = :( – Dominic P Jun 28 '13 at 19:43
@DominicP: This has nothing at all to do with DOS ... – Joey Jun 29 '13 at 8:27
Ha ha, yeah, as soon as I wrote that I figured someone would call me on it. How about: shell scripting in Windows makes me sad? – Dominic P Jun 29 '13 at 17:06
@DominicP: Then use PowerShell; after that shell scripting on Unix makes you sad ;) – Joey Jun 30 '13 at 6:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .