<http://www.netikka.net/tsneti/info/tscmd012.htm>
Copyright © 2003-2011 by Prof. Timo Salmi  
Last modified Sun 4-Dec-2011 10:09:02

 
Assorted NT/2000/XP/.. CMD.EXE Script Tricks
From the html version of the tscmd.zip 1cmdfaq.txt file
To the Description and the Index
 

This page is edited from the 1cmdfaq.txt faq-file contained in my tscmd.zip command line interface (CLI) collection. That zipped file has much additional material, including a number of detached .cmd script files. It is recommended that you also get the zipped version as a companion.

Please see "The Description and the Index page" for the conditions of usage and other such information.



12} How can I rename all my .JPG files sequentially in a folder?

This is an instructive task, so let's go through it in several intermediate steps. First consider
  @echo off & setlocal enableextensions
  set count_=1
  for /f "tokens=*" %%f in (
    'dir /s /b /-c /a:-d-s-h /o:n
    "C:\_G\WWW\~TS\GALLERY2\*.jpg"') do (
    call :_subru1 "%%~f")
  echo End of the first test
  endlocal & goto :EOF
  ::
  :_subru1
  echo %count_% "%~d1" "%~p1" "%~n1" "%~x1"
  set /a count_+=1
  goto :EOF
(As a sideline note how the FOR /F command can be continued onto several lines.)


A screen capture would turn out something like below to demonstrate some of the ~ modifiers on variables. The example also demonstrates incrementing the value of an environment variable (count_) in a loop-like manner. Furthermore observe the handling of the possibility of long file names.
  C:\_D\TEST>cmdfaq
  1 "C:" "\_G\WWW\~TS\GALLERY2\" "ABSORB scaled" ".JPG"
  2 "C:" "\_G\WWW\~TS\GALLERY2\" "ABSORB" ".JPG"
  3 "C:" "\_G\WWW\~TS\GALLERY2\" "BIKEMIR" ".JPG"
  4 "C:" "\_G\WWW\~TS\GALLERY2\" "CATEYE scaled" ".JPG"
  5 "C:" "\_G\WWW\~TS\GALLERY2\" "CATEYE" ".JPG"
  6 "C:" "\_G\WWW\~TS\GALLERY2\" "CRESBAG scaled" ".JPG"
  7 "C:" "\_G\WWW\~TS\GALLERY2\" "CRESBAG" ".JPG"
  8 "C:" "\_G\WWW\~TS\GALLERY2\" "CRESCE2 scaled" ".JPG"
  9 "C:" "\_G\WWW\~TS\GALLERY2\" "CRESCE2" ".JPG"
  10 "C:" "\_G\WWW\~TS\GALLERY2\" "CRESCEN scaled" ".JPG"
  11 "C:" "\_G\WWW\~TS\GALLERY2\" "CRESCENT" ".JPG"
  :
  84 "C:" "\_G\WWW\~TS\GALLERY2\" "TimoSalmi 60v" ".jpg"
  85 "C:" "\_G\WWW\~TS\GALLERY2\" "TimoSalmi 70x100" ".jpg"
  86 "C:" "\_G\WWW\~TS\GALLERY2\" "WELLGO" ".JPG"
  87 "C:" "\_G\WWW\~TS\GALLERY2\PLAIN\" "BIKEMIR_" ".JPG"
  88 "C:" "\_G\WWW\~TS\GALLERY2\PLAIN\" "CRESCE2_" ".JPG"
  89 "C:" "\_G\WWW\~TS\GALLERY2\PLAIN\" "KULKUE_" ".JPG"
  End of the first test
LIMITATIONS: One of the things that we immediately observe is that all potential subfolders are included. If you use paths in the way I did in the above, then you must include the all subfolders switch /s to get at the correct full path. Alternatively, you could drop the /s but then you must run the script in the folder where your relevant *.JPG files are. Else you will get incorrect paths. See later below.

A word for warning. It would be advisable to avoid having "poison characters" &()[]{}^=;!'+,`~ in one's file names when one processes them with command line scripting.

Next step. Let's be prudent and not do the actual renaming but instead create the scripts commands for the purpose:
  @echo off & setlocal enableextensions
  set count_=1
  for /f "tokens=*" %%f in (
    'dir /s /b /-c /a:-d-s-h /o:n
    "C:\_G\WWW\~TS\GALLERY2\*.jpg"') do (
    call :_subru1 "%%~f")
  echo End of the second test
  endlocal & goto :EOF
  ::
  :_subru1
  setlocal
    set dr_=%~d1& set pth_=%~p1& set base_=%~n1& set ext_=%~x1
    echo @ren "%dr_%%pth_%%base_%%ext_%" "%base_%.%count_%%ext_%"
  endlocal
  set /a count_+=1
  goto :EOF
(If you are wondering about the ampersand & it just is to demonstrate putting several commands on one line.)

We would get
  C:\_D\TEST>cmdfaq
  @ren "C:\_G\WWW\~TS\GALLERY2\ABSORB scaled.JPG" "ABSORB scaled.1.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\ABSORB.JPG" "ABSORB.2.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\BIKEMIR.JPG" "BIKEMIR.3.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CATEYE scaled.JPG" "CATEYE scaled.4.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CATEYE.JPG" "CATEYE.5.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESBAG scaled.JPG" "CRESBAG scaled.6.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESBAG.JPG" "CRESBAG.7.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESCE2 scaled.JPG" "CRESCE2 scaled.8.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESCE2.JPG" "CRESCE2.9.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESCEN scaled.JPG" "CRESCEN scaled.10.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESCENT.JPG" "CRESCENT.11.JPG"
  :
  @ren "C:\_G\WWW\~TS\GALLERY2\TimoSalmi 60v.jpg" "TimoSalmi 60v.84.jpg"
  @ren "C:\_G\WWW\~TS\GALLERY2\TimoSalmi 70x100.jpg" "TimoSalmi 70x100.85.jpg"
  @ren "C:\_G\WWW\~TS\GALLERY2\WELLGO.JPG" "WELLGO.86.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\PLAIN\BIKEMIR_.JPG" "BIKEMIR_.87.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\PLAIN\CRESCE2_.JPG" "CRESCE2_.88.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\PLAIN\KULKUE_.JPG" "KULKUE_.89.JPG"
  End of the second test

OK, but that is not quite all what we want. Let's polish by adding leading zeroes so that the added number always is four digits long.
  @echo off & setlocal enableextensions
  set count_=1
  for /f "tokens=*" %%f in (
    'dir /s /b /-c /a:-d-s-h /o:n
    "C:\_G\WWW\~TS\GALLERY2\*.jpg"') do (
    call :_subru1 "%%~f")
  echo rem End of the concluding test
  endlocal & goto :EOF
  ::
  :_subru1
  setlocal
    set dr_=%~d1
    set pth_=%~p1
    set base_=%~n1
    set ext_=%~x1
    set CountWithLead=0000%count_%
    set CountWithLead=%CountWithLead:~-4%
    echo @ren "%dr_%%pth_%%base_%%ext_%" "%base_%.%countWithLead%%ext_%"
  endlocal
  set /a count_+=1
  goto :EOF

  C:\_D\TEST>cmdfaq
  @ren "C:\_G\WWW\~TS\GALLERY2\ABSORB scaled.JPG" "ABSORB scaled.0001.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\ABSORB.JPG" "ABSORB.0002.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\BIKEMIR.JPG" "BIKEMIR.0003.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CATEYE scaled.JPG" "CATEYE scaled.0004.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CATEYE.JPG" "CATEYE.0005.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESBAG scaled.JPG" "CRESBAG scaled.0006.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESBAG.JPG" "CRESBAG.0007.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESCE2 scaled.JPG" "CRESCE2 scaled.0008.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESCE2.JPG" "CRESCE2.0009.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESCEN scaled.JPG" "CRESCEN scaled.0010.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESCENT.JPG" "CRESCENT.0011.JPG"
  :
  @ren "C:\_G\WWW\~TS\GALLERY2\TimoSalmi 60v.jpg" "TimoSalmi 60v.0084.jpg"
  @ren "C:\_G\WWW\~TS\GALLERY2\TimoSalmi 70x100.jpg" "TimoSalmi 70x100.0085.jpg"
  @ren "C:\_G\WWW\~TS\GALLERY2\WELLGO.JPG" "WELLGO.0086.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\PLAIN\BIKEMIR_.JPG" "BIKEMIR_.0087.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\PLAIN\CRESCE2_.JPG" "CRESCE2_.0088.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\PLAIN\KULKUE_.JPG" "KULKUE_.0089.JPG"
  rem End of the concluding test

One further step. Rewrite the above more concisely. The added advantage is that this version is more tolerant of the poison characters.
  @echo off & setlocal enableextensions
  set count_=1
  for /f "tokens=*" %%f in (
    'dir /s /b /-c /a:-d-s-h /o:n
    "C:\_G\WWW\~TS\GALLERY2\*.jpg"') do (
    call :_subru1 "%%~f")
  echo rem End of the concluding test
  endlocal & goto :EOF
  ::
  :_subru1
  setlocal
    set CountWithLead=0000%count_%
    set CountWithLead=%CountWithLead:~-4%
    echo @ren "%~d1%~p1%~n1%~x1" "%~n1.%countWithLead%%~x1"
  endlocal
  set /a count_+=1
  goto :EOF

Now there you have it. Just redirect the output to a command file, and you are all set to do the renaming, maybe after some editing of your own of the resultant command line file.
  C:\_D\TEST>cmdfaq > DOIT.CMD
  C:\_D\TEST>DOIT

Now let's do the same task, but this time omit any subfolders.
  @echo off & setlocal enableextensions
  set dir_=C:\_G\WWW\~TS\GALLERY2
  if not exist "%dir_%\" (
    echo Folder "%dir_%\" not found
    goto :EOF)
  pushd "%dir_%"
  set count_=1
  for /f "tokens=*" %%f in (
    'dir /b /a:-d-s-h /o:n "*.jpg"') do (
    call :_subru1 "%%~f")
  popd
  endlocal & goto :EOF
  ::
  :_subru1
  setlocal
    set CountWithLead=0000%count_%
    set CountWithLead=%CountWithLead:~-4%
    echo @ren "%~d1%~p1%~n1%~x1" "%~n1.%countWithLead%%~x1"
  endlocal
  set /a count_+=1
  goto :EOF

  C:\_D\TEST>cmdfaq
  @ren "C:\_G\WWW\~TS\GALLERY2\ABSORB scaled.JPG" "ABSORB scaled.0001.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\ABSORB.JPG" "ABSORB.0002.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\BIKEMIR.JPG" "BIKEMIR.0003.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CATEYE scaled.JPG" "CATEYE scaled.0004.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CATEYE.JPG" "CATEYE.0005.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESBAG scaled.JPG" "CRESBAG scaled.0006.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESBAG.JPG" "CRESBAG.0007.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESCE2 scaled.JPG" "CRESCE2 scaled.0008.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESCE2.JPG" "CRESCE2.0009.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESCEN scaled.JPG" "CRESCEN scaled.0010.JPG"
  @ren "C:\_G\WWW\~TS\GALLERY2\CRESCENT.JPG" "CRESCENT.0011.JPG"
  :
  @ren "C:\_G\WWW\~TS\GALLERY2\TimoSalmi 60v.jpg" "TimoSalmi 60v.0084.jpg"
  @ren "C:\_G\WWW\~TS\GALLERY2\TimoSalmi 70x100.jpg" "TimoSalmi 70x100.0085.jpg"
  @ren "C:\_G\WWW\~TS\GALLERY2\WELLGO.JPG" "WELLGO.0086.JPG"

The problem can also be solved with a Visual Basic Script (VBScript) aided command line script
  @echo off & setlocal enableextensions
  ::
  :: Set the source folder and check that it contains .JPG files
  set SourceDir=C:\_M
  if not exist "%SourceDir%\*.JPG" (
    echo No .JPG files found in "%SourceDir%"
    goto :EOF)
  ::
  :: Build a Visual Basic Script
  set skip=
  set temp_=%temp%
  if defined mytemp if exist "%mytemp%\" set temp_=%mytemp%
  set vbs_=%temp_%\tmp$$$.vbs
  >"%vbs_%" findstr "'%skip%VBS" "%~f0"
  ::
  :: Run the script with Microsoft Windows Script Host Version 5.6
  cscript //nologo "%vbs_%" "%SourceDir%"
  ::
  :: Clean up
  for %%f in ("%vbs_%") do if exist %%f del %%f
  endlocal & goto :EOF
  '
  'The Visual Basic Script
  '
  Set arg = WScript.Arguments 'VBS
  Set fso = CreateObject("Scripting.FileSystemObject") 'VBS
  Set f = fso.GetFolder(arg(0)) 'VBS
  Set fc = f.Files 'VBS
  Set i=0 'VBS
  For Each f1 in fc 'VBS
    extension = fso.GetExtensionName(f1) 'VBS
    If UCase(extension) = "JPG" Then 'VBS
      i = i + 1 'VBS
      s = "rem @ren " & Chr(34) 'VBS
      s = s & f1 & Chr(34) & " " & Chr(34) 'VBS
      basename = fso.GetBaseName(f1) 'VBS
      s = s & basename 'VBS
      s = s & PadFn(CStr(i),4) 'VBS
      s = s & "." & extension & Chr(34) 'VBS
      Wscript.Echo s 'VBS
    End If 'VBS
  Next 'VBS
  '
  Function PadFn (str, n) 'VBS
    PadFn = Right(String(n-1,"0")&str,n) 'VBS
  End Function 'VBS

The (double safety) output might be e.g. the following. It can be redirected to a new batch file which in turn can be run after one is convinced that it is exactly what one wants.
  C:\_D\TEST>cmdfaq
  rem @ren "C:\_M\ABSORB.JPG" "ABSORB0001.JPG"
  rem @ren "C:\_M\bikemir.jpg" "bikemir0002.jpg"
  rem @ren "C:\_M\CATEYE.JPG" "CATEYE0003.JPG"
  rem @ren "C:\_M\CRESBAG.JPG" "CRESBAG0004.JPG"
  rem @ren "C:\_M\PEUGBAG.JPG" "PEUGBAG0005.JPG"
  rem @ren "C:\_M\PEUGEOT.JPG" "PEUGEOT0006.JPG"
  rem @ren "C:\_M\PRPUMP.JPG" "PRPUMP0007.JPG"
  rem @ren "C:\_M\SKATES.JPG" "SKATES0008.JPG"
  rem @ren "C:\_M\SKIEQUIP.JPG" "SKIEQUIP0009.JPG"
  rem @ren "C:\_M\SONYRAD.JPG" "SONYRAD0010.JPG"
  rem @ren "C:\_M\TACX.JPG" "TACX0011.JPG"
  rem @ren "C:\_M\WELLGO.JPG" "WELLGO0012.JPG"

The original question [M] and the consequent thread in alt.msdos.batch.nt which prompted me to add the VBS-aided solution was "I am attempting to rename a large amount of files using a sequence, i.e.,...I want the files renamed to FILE1.DOC, FILE2.DOC, etc.... any way I can rename about 400 files automatically in a sequence as described."

To do exactly that, the required changes in the code above are minimal. Change JPG to DOC (the two instances) and change
    basename = fso.GetBaseName(f1) 'VBS
to
    basename = "FILE" 'VBS

We might then have an output something like
  C:\_D\TEST>cmdfaq
  rem @ren "C:\_M\OFFISUNS.DOC" "FILE0001.DOC"
  rem @ren "C:\_M\OFFIVIEW.DOC" "FILE0002.DOC"

Below is a true-life pure script I occasionally apply myself:
  @echo off & setlocal enableextensions
  echo @rem +----------------------------------------------------+
  echo @rem : JPGRENAM.CMD Special rename a set of *.jpg files   :
  echo @rem : By Prof. Timo Salmi, Last modified Fri 26-Sep-2008 :
  echo @rem +----------------------------------------------------+
  echo @rem
  ::
  :: Avoid multiple calls of the script. Also see Item #18 CheckLock.
  if exist "%temp%\jpgrenamLockfile.tmp" (
    echo An instance of JPGRENAM.CMD already is running
    echo If this is in error delete the lockfile
    echo "%temp%\jpgrenamLockfile.tmp"
    if not defined cmdbox if defined PauseIfFromDesktop pause
    goto :EOF
    )
  echo Lockfile "%temp%\jpgrenamLockfile.tmp" for JPGRENAM.CMD>"%temp%\jpgrenamLockfile.tmp"
  ::
  :: Parameters, customize the first for your own folder
  set sourceFolder=C:\_M
  set Basename=%~1
  set Number=1
  if not "%~2"=="" set Number=%~2
  ::
  :: Is help needed
  if "%~1"=="" goto _help
  if "%~1"=="?" goto _help
  if "%~1"=="/?" goto _help
  if /i "%~1"=="/help" goto _help
  ::
  :: Any files there?
  if not exist "%sourceFolder%\*.JPG" (
    echo No JPG files found in "%sourceFolder%"
    goto _out
    )
  ::
  :: Process
  pushd "%sourceFolder%"
  for /f "tokens=*" %%f in ('
    dir /b /a-d-s "%sourceFolder%\*.jpg"') do (
      call :ProcessOneFile "%%~ff")
  popd
  echo @dir /b /a-d-s "%sourceFolder%\%Basename%*.jpg"
  goto _out
  ::
  :_help
  echo.
  echo Usage: JPGRENAM [NewBasename] [NewStartNumber]
  echo.
  echo E.g. JPGRENAM Photo 20
  echo JPGRENAM Pict ^> Doit.cmd
  goto _out
  ::
  :_out
  for %%f in ("%temp%\jpgrenamLockfile.tmp") do if exist %%f del %%f
  if not defined cmdbox if defined PauseIfFromDesktop pause
  endlocal & goto :EOF
  ::
  :: ================================================================
  :ProcessOneFile
  setlocal
    set NumberWithLead=000%Number%
    set NumberWithLead=%NumberWithLead:~-3%
    echo @ren "%~nx1" "%Basename%%NumberWithLead%%~x1"
  endlocal
  set /a Number+=1
  goto :EOF

An example screen capture:
[cmd01201.gif]



Consider the following, true situation. Fifteen digital photographs taken on the 3rd of October, 2011. Named as follows
  IMG_20111003_01.JPG
  IMG_20111003_02.JPG
  :
  IMG_20111003_15.JPG
where the last two characters run sequentially. The task is increase the sequential number of the photographs by one. (In fact, to make room for a new IMG_20111003_01.JPG.)

  @echo off & setlocal enableextensions enabledelayedexpansion
  set base_=IMG_20111003_
  for /L %%i in (15, -1, 2) do (
    set n1_=%%i
    set /a n2_=!n1_!-1
    call :LeadFn2 !n1_! n1_
    call :LeadFn2 !n2_! n2_
    rem The echo below is for safety
    echo ren %base_%!n2_!.JPG %base_%!n1_!.JPG)
  endlocal & goto :EOF
  ::
  :LeadFn2
  setlocal enableextensions
    set number_=00%1
    set number_=%number_:~-2%
  endlocal & set "%2=%number_%" & goto :EOF

The output will be:
  C:\_D\TEST>cmdfaq
  ren IMG_20111003_15.JPG IMG_20111003_16.JPG
  ren IMG_20111003_14.JPG IMG_20111003_15.JPG
  :
  ren IMG_20111003_02.JPG IMG_20111003_03.JPG
  ren IMG_20111003_01.JPG IMG_20111003_02.JPG
Note how the sequencing has been programmed to run backwards to avoid renaming collisions.



You might wish to see also Item #107 and Item #178.

References/Comments: (If a Google message link fails try the links within the brackets.)

  Google Groups Jan 1 2004, 6:17 pm [M]
  Using batch parameters Microsoft TechNet
  Google Groups Aug 23 2008, 4:40 pm [M]