Page 1 of 1

Setlocal/Endlocal commands save/restore current directory!

Posted: 27 Mar 2013 10:53
by Aacini

Code: Select all

@echo off
echo Original dir:
cd

rem Save current directory
setlocal
cd ..\..
echo Two levels up:
cd

rem Save current directory
setlocal
cd ..\..
echo Two levels up again:
cd

rem Restore previous dir
endlocal
echo Return to previous dir:
cd

rem Restore previous dir
endlocal
echo Return to original dir:
cd

Output:

Code: Select all

Original dir:
C:\DOCUME~1\Antonio\MYDOCU~1\ASMB\MODERN~1\tests\test
Two levels up:
C:\DOCUME~1\Antonio\MYDOCU~1\ASMB\MODERN~1
Two levels up again:
C:\DOCUME~1\Antonio\MYDOCU~1
Return to previous dir:
C:\DOCUME~1\Antonio\MYDOCU~1\ASMB\MODERN~1
Return to original dir:
C:\DOCUME~1\Antonio\MYDOCU~1\ASMB\MODERN~1\tests\test


Tested on Win-XP. As far as I know, this feature is undocumented!

http://stackoverflow.com/questions/15656927/restore-default-working-dir-if-bat-file-is-terminated-abruptly

Antonio

Re: Setlocal/Endlocal automatically push/pop current directo

Posted: 27 Mar 2013 11:04
by Squashman
Cool Stuff!
Windows 7 64 bit output.

Code: Select all

Original dir:
C:\Users\Squashman\Documents\Downloads\Baseball\tests\test
Two levels up:
C:\Users\Squashman\Documents\Downloads\Baseball
Two levels up again:
C:\Users\Squashman\Documents
Return to previous dir:
C:\Users\Squashman\Documents\Downloads\Baseball
Return to original dir:
C:\Users\Squashman\Documents\Downloads\Baseball\tests\test

Re: Setlocal/Endlocal automatically push/pop current directo

Posted: 28 Mar 2013 06:12
by Endoro
setlocal/endlocal do restore the current directory but do not clear the pushd directory stack and do not remove with pushd created LAN drive letters

Re: Setlocal/Endlocal automatically push/pop current directo

Posted: 29 Mar 2013 00:37
by Aacini
Endoro wrote:setlocal/endlocal do restore the current directory but do not clear the pushd directory stack and do not remove with pushd created LAN drive letters


Of course, I mentioned nothing about the relation of Setlocal/Endlocal commands with Pushd/Popd commands because it does not exists! It is funny that you think that this relation may be assumed, so it is necessary to clear that this relation does not exist! :wink:

The title of this topic is an easier way to explain the behavior of Setlocal/Endlocal commands with respect to the current directory, instead of an explanation like this one: "Setlocal saves the current directory and Endlocal restore the directory saved by the last Setlocal command executed, that is to say, if Setlocal is executed several times, each Endlocal matchs the most recent Setlocal, so the directory saved by the first Setlocal command executed will be restored by the last Endlocal command executed".

Antonio

Re: Setlocal/Endlocal automatically push/pop current directo

Posted: 29 Mar 2013 02:42
by Endoro
"endlocal automatically restores %cd%"

(btw. no surprising news about environment variables)

Re: Setlocal/Endlocal automatically push/pop current directo

Posted: 08 Oct 2014 03:56
by dbenham
The use of the words push/pop in the title can lead to confusion with the PUSHD and POPD commands.

I would phrase the current directory behavior as:
ENDLOCAL restores the current directory to the value that existed when the matching SETLOCAL was executed.

Re: Setlocal/Endlocal automatically push/pop current directo

Posted: 08 Oct 2014 09:35
by Aacini
dbenham wrote:The use of the words push/pop in the title can lead to confusion with the PUSHD and POPD commands.

I would phrase the current directory behavior as:
ENDLOCAL restores the current directory to the value that existed when the matching SETLOCAL was executed.


Ok. I rephrased the topic title and the description of the behaviour. Is there any comment about the topic?

This is my point of view: %CD% variable (current directory) is NOT stored into the environment, but created by cmd.exe when %CD% is used, in the same way as %DATE%, %TIME%, %RANDOM% and other dynamic variables. However, SETLOCAL/ENDLOCAL commands make %CD% variable behave like if it was stored in the environment, like any other regular variable! This is a very particular mechanism that, in my opinion, requires that SETLOCAL command store the current directory in a memory area separated from the environment, but paralell to it (that is, to each instance of the environment), and that ENDLOCAL command restore current directory from such area.

I would like to know if this behaviour could be explained by other simpler mechanism and if this point is documented at any place...

Antonio

Re: Setlocal/Endlocal commands save/restore current director

Posted: 08 Oct 2014 13:06
by pieh-ejdsch
This "Howto - work with Variables in Batch/CMD" i've wrote in 2009
http://www.administrator.de/wissen/wie-arbeite-ich-mit-batch-umgebungsvariablen-erstellung-umgang-erweiterungen-ver%C3%A4nderungen-117069.html

Also The path is the location too.

This was the beginning with batch for me. I had read all Documented Help in XP for Command Line.
The explains from this Help-Dokus for me was not very good to understand. Perhaps i wrote an Explaination for others like me and learn "to think- trought a corner" inGerman " Um die Ecke denken"

This. Information is to read from Commandline Referenz.
Phil

Re: Setlocal/Endlocal automatically push/pop current directo

Posted: 08 Oct 2014 15:21
by dbenham
Aacini wrote:This is my point of view: %CD% variable (current directory) is NOT stored into the environment, but created by cmd.exe when %CD% is used, in the same way as %DATE%, %TIME%, %RANDOM% and other dynamic variables. However, SETLOCAL/ENDLOCAL commands make %CD% variable behave like if it was stored in the environment, like any other regular variable! This is a very particular mechanism that, in my opinion, requires that SETLOCAL command store the current directory in a memory area separated from the environment, but paralell to it (that is, to each instance of the environment), and that ENDLOCAL command restore current directory from such area.
I am in total agreement. Your description is compatible with my description of dynamic variables (type 1) found at http://stackoverflow.com/a/20169219/1012053. I also agree that the saved current directory info must be distinct from the saved environment info.

I have never seen any documentation describing the current directory behavior. It makes me wonder if there are any other ??? that are saved and restored by SETLOCAL/ENDLOCAL. But I haven't found anything other than true environment variables and the current directory (including current drive).

I've tested the following (on Win 7), but none are restored by ENDLOCAL:

ECHO state
DOSKEY macros
COLOR
MODE (I've only tested window and buffer sizes)

For a brief moment I thought that perhaps PROMPT was special, but then I realized that it is normal environment variable restoration at play. CMD.EXE uses the value of the PROMPT variable to determine what gets displayed when ECHO is ON.

The PROMPT command simply sets the PROMPT environment variable - it is a functional synonym for SET PROMPT=

PROMPT without any arguments simply undefines the PROMPT variable.

The trick is that CMD.EXE defaults to $P$G if the PROMPT variable is not defined. The other oddity is that during intialization, CMD.EXE automatically defines PROMPT=$P$G if PROMPT is not already defined.


Dave Benham

Re: Setlocal/Endlocal commands save/restore current director

Posted: 08 Oct 2014 18:25
by Liviu
Looks like endlocal restores not just the "current working directory" (%cd%), but also the "current directory" on each drive (%=C:% etc) - which includes removing =X: pseudo variables that may have been created inside the block.

Code: Select all

:: assumes C:, D:, E: each have \tmp\1, \tmp\2 directories
@echo off

cd D:\tmp\1
call :cwds

setlocal
cd C:\tmp\2
cd D:\tmp\2
cd E:\tmp\2
call :cwds
endlocal

call :cwds
goto :eof

:cwds
echo.
echo cd=%cd%
set "" | find ":="
On win7x64.sp1...

Code: Select all

C:\tmp\1>cwd-test

cd=C:\tmp\1
=C:=C:\tmp\1
=D:=D:\tmp\1

cd=C:\tmp\2
=C:=C:\tmp\2
=D:=D:\tmp\2
=E:=E:\tmp\2

cd=C:\tmp\1
=C:=C:\tmp\1
=D:=D:\tmp\1

C:\tmp\1>

Liviu

P.S. Somewhat funny that cmd "emulators" have the endlocal behavior spelled out (at least for the current working directory on the current drive), while cmd itself leaves it undocumented:
- 4nt/tcc http://jpsoft.com/help/endlocal.htm "The SETLOCAL command saves the current disk drive, default directory, all environment variables ..." and the behavior dates back to early 4dos versions;
- wine https://www.winehq.org/pipermail/wine-cvs/2007-March/030894.html "cmd.exe: setlocal and endlocal should preserve drive and directory".

Re: Setlocal/Endlocal commands save/restore current director

Posted: 08 Oct 2014 20:03
by dbenham
Good catch, that makes sense.

Note that the = variables like %=C:% are true environment variables (type 2 in my StackOverflow post). The values are dynamic in that they are set automatically every time CD or PUSHD or POPD makes a change.


Dave Benham