Setlocal/Endlocal commands save/restore current directory!

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Aacini
Expert
Posts: 1676
Joined: 06 Dec 2011 22:15
Location: México City, México

Setlocal/Endlocal commands save/restore current directory!

#1 Post by Aacini » 27 Mar 2013 10:53

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
Last edited by Aacini on 08 Oct 2014 09:16, edited 3 times in total.

Squashman
Expert
Posts: 4206
Joined: 23 Dec 2011 13:59

Re: Setlocal/Endlocal automatically push/pop current directo

#2 Post by Squashman » 27 Mar 2013 11:04

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

Endoro
Posts: 244
Joined: 27 Mar 2013 01:29
Location: Bozen

Re: Setlocal/Endlocal automatically push/pop current directo

#3 Post by Endoro » 28 Mar 2013 06:12

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

Aacini
Expert
Posts: 1676
Joined: 06 Dec 2011 22:15
Location: México City, México

Re: Setlocal/Endlocal automatically push/pop current directo

#4 Post by Aacini » 29 Mar 2013 00:37

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

Endoro
Posts: 244
Joined: 27 Mar 2013 01:29
Location: Bozen

Re: Setlocal/Endlocal automatically push/pop current directo

#5 Post by Endoro » 29 Mar 2013 02:42

"endlocal automatically restores %cd%"

(btw. no surprising news about environment variables)

dbenham
Expert
Posts: 2404
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Setlocal/Endlocal automatically push/pop current directo

#6 Post by dbenham » 08 Oct 2014 03:56

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.

Aacini
Expert
Posts: 1676
Joined: 06 Dec 2011 22:15
Location: México City, México

Re: Setlocal/Endlocal automatically push/pop current directo

#7 Post by Aacini » 08 Oct 2014 09:35

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

pieh-ejdsch
Posts: 232
Joined: 04 Mar 2014 11:14
Location: germany

Re: Setlocal/Endlocal commands save/restore current director

#8 Post by pieh-ejdsch » 08 Oct 2014 13:06

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
Last edited by pieh-ejdsch on 08 Oct 2014 23:13, edited 1 time in total.

dbenham
Expert
Posts: 2404
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Setlocal/Endlocal automatically push/pop current directo

#9 Post by dbenham » 08 Oct 2014 15:21

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

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: Setlocal/Endlocal commands save/restore current director

#10 Post by Liviu » 08 Oct 2014 18:25

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".

dbenham
Expert
Posts: 2404
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Setlocal/Endlocal commands save/restore current director

#11 Post by dbenham » 08 Oct 2014 20:03

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

Post Reply