I have a deployment directory that contains subdirectories, one for each deployment. I'm trying to write a batch script that, among other things, performs a cd
into the newest one of these directories.
I know how to do this in bash
(has already been ansered here as well), but I don't know how to accomplish the same thing in Windows cmd
. Can anyone help me?
In a batch file following lines can be used to changed to the subdirectory with newest modification date:
@echo off
for /F "eol=| delims=" %%I in ('dir * /AD /B /O-D 2^>nul') do cd "%%I" & goto DoneCD
echo No subdirectory found in: "%CD%"
:DoneCD
The command FOR with option /F
starts a new command process with %ComSpec% /c
and the command line specified between '
as further arguments in background. So executed by FOR is with usual Windows installation path:
C:\Windows\System32\cmd.exe /c dir * /AD /B /O-D 2>nul
DIR executed by background command process searches with the specified arguments
/AD
(attribute directory)*
(all)and outputs
/B
just the directory names without path never enclosed in "
/O-D
and not using option /TC
(creation date) or /TA
(last access date) which means first the newest modified directory and last the oldest modified directory.The output by DIR is written to handle STDOUT of the started background command process.
2>nul
redirects the error message output by DIR on not finding any directory in current directory from handle STDERR to device NUL to suppress this error message.
Read the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul
. The redirection operator >
must be escaped with caret character ^
on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir
command line with using a separate command process started in background.
FOR captures everything written by DIR to handle STDOUT of started command process and processes this output line by line after started cmd.exe
terminated itself.
FOR ignores empty lines which do not occur here because of DIR outputs the list of directory names without empty lines because of using /B
.
FOR would split up by default a line into substrings (tokens) using normal space and horizontal tab character as delimiters. After this substring splitting is done FOR would by default check if the first substring starts with default end of line character ;
in which case the line would be ignored like an empty line. Otherwise FOR would assign first space/tab delimited string to the specified loop variable I
and would execute the command line with CD and GOTO.
A directory name could be for example ;Test Folder
, i.e. a directory name starting with a space and a semicolon and containing one more space. Such a directory name would be split up to ;Test
(without space at beginning) and Folder
and next ignored by FOR because of ;Test
starts with a semicolon.
For that reason the end of line character is redefined from default semicolon to a vertical bar with eol=|
which is a character no file or folder name can contain according to Microsoft documentation about Naming Files, Paths, and Namespaces. And line splitting behavior is disabled with delims=
at end of options argument string after for /F
which defines an empty list of delimiters. So the directory name as output by DIR is assigned to loop variable I
without any modification even on being a very unusual name for a directory.
FOR executes command CD which changes current directory to the last modified subdirectory of the current directory and next command GOTO is executed to continue the processing of the batch file on the line below the label line :DoneCD
. So the FOR loop execution is broken already after processing first directory name with command GOTO.
It is of course possible to use other commands after the FOR command line and the label line :DoneCD
than just the ECHO line reporting that no subdirectory was found in current directory as shown by referencing dynamic environment variable CD
like a command line to exit batch processing on this unusual use case or error condition case.
This FOR command line with the command GOTO to exit FOR loop after CD cannot be used in a Windows command prompt window. A solution for Windows command prompt window would be:
set "DoneCD=" & (@for /F "eol=| delims=" %I in ('dir * /AD /B /O-D 2^>nul') do @if not defined DoneCD cd "%I" & set "DoneCD=1") & set "DoneCD="
In a batch file this single line with multiple commands would be written as
@set "DoneCD=" & (@for /F "eol=| delims=" %%I in ('dir * /AD /B /O-D 2^>nul') do @if not defined DoneCD cd "%%I" & set "DoneCD=1") & set "DoneCD="
or better readable in its multi-line version with an additional echo
as
@echo off
set "DoneCD="
for /F "eol=| delims=" %%I in ('dir * /AD /B /O-D 2^>nul') do (
if not defined DoneCD (
cd "%%I"
set "DoneCD=1"
)
)
if not defined DoneCD echo No subdirectory found in: "%CD%"
set "DoneCD="
First the environment variable DoneCD
is deleted if it is defined by chance.
Next FOR runs cmd.exe
with DIR as described above and processes the first output directory with newest modification date. The IF condition is true on newest directory as the environment variable was definitely undefined before execution of FOR. So command CD is executed to change the current directory to newest subdirectory. Then the environment variable DoneCD
is defined with value 1
. Any other value would be also possible like on using set "DoneCD=%%I"
. Important here is that for the other subdirectories output by DIR the environment variable DoneCD
is now defined and so the IF condition is always false. So there is no attempt made to change in current subdirectory of initial current directory into a subdirectory not existing here or existing by chance also in the subdirectory.
Finally the environment variable DoneCD
is deleted again if defined at all during execution of FOR.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
cd /?
dir /?
echo /?
for /?
goto /?
if /?
set /?
... explaining on last help page dynamic environment variable CD
.