How do I get the current directory name in a windows command prompt inside of FOR loop?

I'm using Win-10 64-bit.

Given the following directory structure on my windows machine...

c:\tmp\Logs_UAT\
'-> folder1
| '-> test.txt
'-> folder2 '-> test.txt

...I'm trying to rename all files in each directory by prefixing them with the directory name, to have:

c:\tmp\Logs_UAT\
'-> folder1
| '-> folder1_test.txt
'-> folder2 '-> folder2_test.txt

In order to achieve this, I'm looping recursively through files in the %basedir% using FOR and in each directory I'm getting a current directory name using the inner FOR "loop", and then doing a rename. However, current directory is usually not derived correctly. Here's the .bat file which allows to reproduce the issue:

@echo off
set basedir=c:\tmp\Logs_UAT
for /R %basedir% %%I in (*) DO (
cd %%~pI
for %%G in (.) do echo %%~nxG> temp.temp
set /P curdir=<temp.temp
del /f temp.temp
echo.
echo -------------------
echo %%I
dir
echo %curdir%
echo -------------------
)

It outputs the same value for %curdir% for both files:

C:\tmp>test.bat
-------------------
c:\tmp\Logs_UAT\folder1\test.txt Datenträger in Laufwerk C: ist OSDisk Volumeseriennummer: D280-2DC0 Verzeichnis von C:\tmp\Logs_UAT\folder1
06.05.2020 19:29 <DIR> .
06.05.2020 19:29 <DIR> ..
06.05.2020 19:02 0 test.txt 1 Datei(en), 0 Bytes 2 Verzeichnis(se), 291.684.151.296 Bytes frei
folder2
-------------------
.
-------------------
c:\tmp\Logs_UAT\folder2\test.txt Datenträger in Laufwerk C: ist OSDisk Volumeseriennummer: D280-2DC0 Verzeichnis von C:\tmp\Logs_UAT\folder2
06.05.2020 19:29 <DIR> .
06.05.2020 19:29 <DIR> ..
06.05.2020 19:02 0 test.txt 1 Datei(en), 0 Bytes 2 Verzeichnis(se), 291.684.151.296 Bytes frei
folder2
-------------------
C:\tmp\Logs_UAT\folder2>

I tried:

  1. Fresh console window
  2. Console and batch file
  3. Sometimes I'm getting the first folder name and sometimes second
  4. Lots of search on the internet

I'd prefer to stick to standard windows utilities as I have to distribute the script to other users which might not have the extra software.

How do I get the current directory name in a windows command prompt inside of FOR loop?

2

3 Answers

Indeed DelayedExpansion helped, thanks DavidPostill. Here's the working script:

@echo off
SETLOCAL EnableDelayedExpansion
set basedir=c:\tmp\Logs_UAT
for /R %basedir% %%I in (*) DO (
cd %%~pI
for %%G in (.) do echo %%~nxG> temp.temp
set /P curdir=<temp.temp
del /f temp.temp
echo !curdir!
)
endlocal
  • For you to get the same result as in your question, in one loop:
@echo off
set "_=echo\ -------------------"
for /D /R "c:\tmp\Logs_UAT" %%I in (*
)do %_% & echo\%%~nxI & dir "%%~nxI" & echo\ %%~nxI & %_%
  • Your output:
 ------------------- Volume in drive C has no label. Volume Serial Number is 32E8-70C5 Directory of c:\tmp\Logs_UAT\folder1
05/06/2020 02:40 PM <DIR> .
05/06/2020 02:40 PM <DIR> ..
05/06/2020 02:41 PM 8 test.txt 1 File(s) 8 bytes 2 Dir(s) 3,128,999,936 bytes free folder1 ------------------- ------------------- Volume in drive C has no label. Volume Serial Number is 32E8-70C5 Directory of c:\tmp\Logs_UAT\folder2
05/06/2020 02:47 PM <DIR> .
05/06/2020 02:47 PM <DIR> ..
05/06/2020 02:48 PM 7 folder2.txt 1 File(s) 7 bytes 2 Dir(s) 3,128,999,936 bytes free folder2 -------------------

  1. You don't need to use more than one for loop, use for /D /R, in one loop recursive in all subdirectories, and this makes DelayedExpansion not necessary

  2. Why need to create and delete a file temp.temp in the entire directory using for /D with any additional for loop? When you already have the name of the current folder in your loop (/Recursive in all sub/Directories) stored in the variable %%~nxI (and many others available expansively too), so, for to use in your looping, just use them...

    • Use the FOR variable syntax replacement:
      %~pI - expands %I to a path only
      %~nI - expands %I to a file name only
      %~xI - expands %I to a file extension only
    • The modifiers can be combined to get compound results:
      %~pnI - expands %I to a path and file name only
      %~pnxI - expands %I to a path, file name and extension only
    • )do %_% & echo\%%~nxI & dir "%%~nxI" & echo\ %%~nxI & %_%

      Obs.: About using %%~x in directory name observation note in ss64.com:

    • Full Stop BugAlthough Win32 will not recognise any file or directory name that begins or ends
      with a '.' (period/full stop) it is possible to include a Full Stop in the middle
      of a directory name and this can cause issues with FOR /D.
    • Parameter expansion will treat a Full Stop as a file extension, so for a directory
      name like "Sample 2.6.4" the output of %%~nI will be truncated to "Sample 2.6" to
      return the whole folder name use %%I or %%~nxI
  3. You don't need to use DelayedExpansion, you can use cmd /v/c echo\!curdir! or echo\%%~nxI

  4. For get output as the same of your code output question, you can set/use a variable for your banner (set _=echo\ ----), adjust this to desired layout output:

    • )do %_% & echo\%%~nxI & dir "%%~nxI" & echo\ %%~nxI & %_%

    Or, in one conventional formatting

    • @echo off
      set "_=echo\ -------------------"
      for /D /R "c:\tmp\Logs_UAT" %%I in (*)do (
      %_%
      echo\%%~nxI
      dir "%%~nxI"
      echo\ %%~nxI
      %_%
      )
  5. For one simple and short output option in one line with for /D /R loop, you can try:

    • @echo off
      for /d /r "c:\tmp\Logs_UAT" %%I in (*)do set "curdir=%%~nxI" && cmd /v /c " echo\!curdir!"

0

My general solution to find all levels of directories:

@ECHO OFF
setlocal enabledelayedexpansion EnableExtensions
::Sample BAT to find all levels directories
:: FULL current path: "G:\First our directory\Second our directory\Third. - Strange . directory\Fourth and last directory"
:: Get full current path (could be passed as a parameter to use as subroutine)
SET ActualP=%CD%
:: Set starting counter number
SET /A Countdir=0
:: Find number of directorie levels, echoes them to console and set associated variables
FOR %%G in ("%ActualP:\=" "%") DO (SET /A "CountDir+=1" set "Lvl=%%G" set "Lvl!Countdir!=!Lvl!" ECHO Lvl!Countdir!:!Lvl! )
ECHO.
:: Check number of levels to console
ECHO Levels of directorie: %CountDir%
ECHO.
:: Get last (current) level of directory free of double quotes and echoes it to console
:: between brackets to assure not extra chars are present
SET "LastLvl=%Lvl:"=%"
ECHO LastLvl: [%LastLvl%]
:: Just to be sure that the variables have been set:
ECHO.
ECHO Third level of directorie: %Lvl3%
PAUSE
EXIT
:: This wiil echoes to console:
::
:: Lvl1:"G:"
:: Lvl2:"First our directory"
:: Lvl3:"Second our directory"
:: Lvl4:"Third. - Strange . directory"
:: Lvl5:"Fourth and last directory"
::
:: Levels of directorie: 5
::
:: LastLvl: [Fourth and last directory]
::
:: Third level of directorie: "Second our directory"
:: Premere un tasto per continuare . . .

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like