I want to run a .bat script which makes a file and save it with the same name as the folder it is in. I want it to start in a map and loop through the submaps. I started with this code below and run it in one of the submaps. That works, I get a file with the name of the submap.
FOR /D %%I IN ("%CD%") DO SET _LAST_SEGMENT_=%%~nxI
ECHO Last segment = "%_LAST_SEGMENT_%"
echo.>%_LAST_SEGMENT_%.mp4
pause
So now I only have to place it in a for loop. So I made the code below, which is not working. It seems that the %CD%
is referring to my parent map(subfolders), where the .bat
file is located, instead of my submaps (video1, video2, etc.).
Set Base=C:\Video\subfolders
FOR /R "%Base%" %%F IN (.) DO (
PushD "%%F"
FOR /D %%I IN ("%CD%") DO SET _LAST_SEGMENT_=%%~nxI
echo %CD%
ECHO Last segment = "%_LAST_SEGMENT_%"
echo.>%_LAST_SEGMENT_%.mp4
PopD
)
Pause
Output:
C:\Video\subfolders>Set Base=C:\Video\subfolders
C:\Video\subfolders>FOR /R "C:\Video\subfolders" %F IN (.) DO (
PushD "%F"
FOR / %I IN ("C:\Video\subfolders") DO SET _LAST_SEGMENT_=%~nxI
echo C:\Video\subfolders
ECHO Last segment = ""
echo. 1>.mp4
PopD
)
C:\Video\subfolders>(
PushD "C:\Video\subfolders\."
FOR / %I IN ("C:\Video\subfolders") DO SET _LAST_SEGMENT_=%~nxI
echo C:\Video\subfolders
ECHO Last segment = ""
echo. 1>.mp4
PopD
)
C:\Video\subfolders>SET _LAST_SEGMENT_=subfolders
C:\Video\subfolders
Last segment = ""
C:\Video\subfolders>(
PushD "C:\Video\subfolders\video1\."
FOR / %I IN ("C:\Video\subfolders") DO SET _LAST_SEGMENT_=%~nxI
echo C:\Video\subfolders
ECHO Last segment = ""
echo. 1>.mp4
PopD
)
C:\Video\subfolders\video1>SET _LAST_SEGMENT_=subfolders
C:\Video\subfolders
Last segment = ""
C:\Video\subfolders>(
PushD "C:\Video\subfolders\video2\."
FOR / %I IN ("C:\Video\subfolders") DO SET _LAST_SEGMENT_=%~nxI
echo C:\Video\subfolders
ECHO Last segment = ""
echo. 1>.mp4
PopD
)
C:\Video\subfolders\video2>SET _LAST_SEGMENT_=subfolders
C:\Video\subfolders
Last segment = ""
C:\Video\subfolders>(
PushD "C:\Video\subfolders\video3\."
FOR / %I IN ("C:\Video\subfolders") DO SET _LAST_SEGMENT_=%~nxI
echo C:\Video\subfolders
ECHO Last segment = ""
echo. 1>.mp4
PopD
)
C:\Video\subfolders\video3>SET _LAST_SEGMENT_=subfolders
C:\Video\subfolders
Last segment = ""
C:\Video\subfolders>Pause
Press any key to continue . . .
I saw the link below which explain to use setlocal enabledelayedexpansion
but I can’t get this to work.
https://superuser.com/questions/503488/why-doesnt-cd-work-after-using-pushd-to-a-unc-path
Any advice would be appreciated
It looks like you want something like:
@echo off
for /F "delims=" %%I in ('dir "C:\Video\subfolders\*" /AD-H /B /S 2^>nul') do (
pushd "%%I"
echo/>"%%~nxI.mp4"
popd
)
The commands pushd
and popd
are not really necessary as demonstrated with below code:
@echo off
for /F "delims=" %%I in ('dir "C:\Video\subfolders\*" /AD-H /B /S 2^>nul') do (
echo Directory is: %%I
echo/>"%%I\%%~nxI.mp4"
)
The command FOR runs in a separate command process started with cmd.exe /C
in background the command line:
dir "C:\Video\subfolders\*" /AD-H /B /S 2>nul
The command DIR outputs to handle STDOUT of this background command process
/B
just all names with full path because of option /S
/AD-H
(attribute directory and not hidden)C:\Video\subfolders
and all its subdirectories.The error message output by DIR to handle STDERR on not finding any directory entry in entire directory tree of C:\Video\subfolders
is suppressed by redirecting it to device NUL.
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 the output to STDOUT of started command process and processes this output line by line with ignoring empty lines and by default also lines starting with a semicolon which both do not occur here.
FOR would also split up every line into substrings on spaces/tabs and would assign just first space/tab separated string to specified loop variable I
. Directory names can have spaces and for that reason delims=
is used to define an empty list of string delimiters resulting in getting assigned to loop variable I
always the entire full qualified directory name currently processed from captured DIR output.
The name of the directory without path is referenced with %%~nxI
which is the string after last backslash. A directory name can contain also a dot like folder.name
or start with a dot like .FolderName
although both are unusual on Windows. For that reason it is necessary to use %%~nxI
(name and extension) and not just %%~nI
because of FOR does not verify if string referenced with %%I
is a file or directory name.
%%~nI
references the string between last \
(or /
for compatibility with Linux paths replaced all first by \
) if there is any backslash (or slash) at all or beginning of string if there is no \
(or /
) and last dot if there is a .
at all after already determined beginning of name string or end of string if there is no dot. %%~xI
references the string beginning with last dot found after last directory separator. So the string assigned to loop variable I
must not be a file/folder name of a really existing file/folder although this is the case here. %%~nxI
would be an empty string if I
holds a string ending with \
(or /
).
Do not assign a string which can be referenced using a loop variable without or with a modifier to an environment variable as this would require the usage of delayed expansion as explained by help of command SET output on running in a command prompt window set /?
.
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.
dir /?
echo /?
for /?
popd /?
pushd /?
See also DosTips forum topic ECHO. FAILS to give text or blank line - Instead use ECHO/.
The second batch file code in question does not work because of not using delayed expansion or avoiding the usage of environment variables defined/modified inside a command block and referenced within same command block using syntax %variable%
. The Windows command processor cmd.exe
parses the entire command block from (
of first FOR to matching )
before executing the outer FOR the first time. See How does the Windows Command Interpreter (CMD.EXE) parse scripts? All %variable%
references within this command block are replaced during this preprocessing phase already by current value of the referenced environment variable. So the code finally executed on iterating outer FOR does not contain anymore any %variable%
environment variable reference as it can be seen on command lines output by cmd.exe
before executing the command line.