2

I would like to create a Windows batch file "printFileNames.bat" that print custom file names as follows:
Adobe_1, DIFX_2, WinRAR_3...

I cannot figure out how to work with variables in a loop. This is what I have:

for /r C:\myDir\ %%i in (*) do (
   set counter=counter+1
   set myFileName=%%i+counter
   echo myFileName >> C:\list.txt
)
xeo gegry
  • 131
  • 1
  • 3
  • 5

4 Answers4

4

It is possible to obtain the required output without using an explicit counter:

@ECHO OFF
FOR /F "delims=: tokens=1*" %%R IN ('DIR /A-D-H /B /S D:\to_delete\* ^| FINDSTR /N .') DO (
  ECHO %%~dpnS_%%R%%~xS
)

The DIR command provides the list of files, FINDSTR supplies it with numbers, the FOR /F loop processes thee output of FINDSTR to separate numbers from file names and ECHO produces the final output where numbers are appended to the file names.

Note that the numbers get appended to the names, i.e. before the extensions, so that a file name like this:

D:\path\name.ext

changes to something like this:

D:\path\name_1.ext

If you actually want it to be like this:

D:\path\name.ext_1

replace the ECHO command above with the following:

ECHO %%S_%%R
Andriy M
  • 76,112
  • 17
  • 94
  • 154
3

Three things to know:

  1. If you want to perform variable arithmetic, use the set /a command (the documentation is a bit outdated though).
  2. If you want to employ if statements inside the for loop, they will break the loop. You can use call to call an inner subroutine, and users if from there. The parameters in the subroutine are passed through the variables %1, %2, etc... (just like in an ordinary batch file).
  3. Lets assume a full path is stored in %%f. If you want to extract just the name without the extension, use the %%~nf form.

That being said, try the following code:

    @echo off
    set counter=0
    for /r "C:\myDir\" %%f in (*) do (
        set /a counter+=1
        call :HandleFile "%%f"
    )
    goto :eof

:HandleFile
    if "%~x1"==".jpg" goto :eof
    if "%~x1"==".gif" goto :eof

    set "myFileName=%~n1_%counter%"
    for %%^" in ("") do >>C:\list.txt echo %%~"%myFileName%

EDIT: fixed the script to handle special file names and skip files with certain extensions.

Hope it helps!

Eitan T
  • 32,660
  • 14
  • 72
  • 109
  • You cannot use an `if` statement in a `for` loop, because it will break the loop. You'll need to call a subroutine from within the loop, and do your stuff from there. See my edited answer. – Eitan T Jun 12 '12 at 17:06
  • Thanks a lot everybody. You saved my day. – xeo gegry Jun 12 '12 at 17:28
  • @EitanT: Excuse me, but an `if` inside a `for` does _NOT_ break it; you may use any `if` and `for` commands combination nested at any level with no problem at all! What _DOES_ break a `for` command is a `goto`! – Aacini Jun 13 '12 at 02:40
  • @Aacini you are right, I stand corrected. But the code in my answer is still completely correct... – Eitan T Jun 13 '12 at 06:41
  • @Eitan T - You should use `set "myFileName=%~n1_%counter%"`, else it will fail for filenames with special characters like `Cat&Dog.txt` – jeb Jun 13 '12 at 07:02
  • @Eitan T- I missed the obvious, now the `set "...` works but the code will fail in the next line `echo Cat&Dog.txt`. This can be solved with [disappearing quotes](http://stackoverflow.com/a/4645113/463115) `for %%^" in ("") do echo %%~"%var%` – jeb Jun 13 '12 at 10:41
  • @jeb What you've suggested works for a simple `echo` command, but it doesn't work properly when you add the `>>list.txt` to it. It doesn't redirect it to the file. – Eitan T Jun 13 '12 at 11:03
  • 1
    @Eitan T - As it's a disappearing quote, you need two of them `for %%^" in ("") do echo %%~"%var%%%~" >> list.txt` or change the order `for %%^" in ("") do >> list.txt echo %%~"%var%` – jeb Jun 13 '12 at 11:12
  • +1: @jeb, very elegant, love it. Thanks for the info, everyday I learn something new! – Eitan T Jun 13 '12 at 11:23
1

You need delayed expansion to access the value of the counter in your loop.
And for incrementing your counter you need the SET /A switch.

setlocal EnableDelayedExpansion
set counter=0
for /r C:\myDir\ %%i in (*) do (
  set /a counter=counter+1
  set "myFileName=%%i_!counter!"
  echo !myFileName!>> C:\list.txt
)

This would fail if your filenames contains exclamation marks !, then you need a more stable version like this one

setlocal DisableDelayedExpansion
set counter=0
for /r C:\myDir\ %%i in (*) do (
  set /a counter=counter+1
  set "filename=%%i"

  setlocal EnableDelayedExpansion
  set "myFileName=!filename!_!counter!"
  echo !myFileName!>> C:\list.txt
  endlocal
)
jeb
  • 78,592
  • 17
  • 171
  • 225
1
@echo off
setLocal EnableDelayedExpansion

set N=0
for /f "tokens=1 delims=." %%i in ('dir /b C:\mydir\') do (
    set /a N+=1 
    echo %%i_!N!
)
GuillaumeS
  • 1,578
  • 1
  • 14
  • 15