0

Edit: Just found out this is not an uncommon question, and my question was flagged duplicate of At which point does `for` or `for /R` enumerate the directory (tree)?

Question:

I have 2 files where I want to replace _ with _1 with a batch file using REN.

IMG_0002.JPG --> IMG_10002.JPG
IMG_0013.JPG --> IMG_10013.JPG

I am using this script:

for %%a in (IMG_*.*) do call :next %%a
pause
GOTO:EOF

:next
set newname=%1
set newname=%newname:_=_1%
ren %1 %newname%

The problem is, that the loop is running not 2 times but 3 times:

for %a in (IMG_*.*) do call :next %a

call :next IMG_0002.JPG
set newname=IMG_0002.JPG
set newname=IMG_10002.JPG
ren IMG_0002.JPG IMG_10002.JPG

call :next IMG_0013.JPG
set newname=IMG_0013.JPG
set newname=IMG_10013.JPG
ren IMG_0013.JPG IMG_10013.JPG

call :next IMG_10002.JPG
set newname=IMG_10002.JPG
set newname=IMG_110002.JPG
ren IMG_10002.JPG IMG_110002.JPG

pause

Leaving me with these 2 file names:

IMG_110002.JPG
IMG_10013.JPG

Any idea what's going on and how to fix the script?

Thank you

  • The issue is with the `FOR` command. It will see the newly renamed file as a file it has to iterate. So you use this instead. `for /F "delims=" %%a in ('dir /b /a-d IMG_*.*') do call :next %%a` – Squashman Oct 12 '20 at 23:21
  • What does `dir /X IMG_*.*` return? – aschipfl Oct 13 '20 at 07:42
  • @Squashman this is actually the only way I thought this could happen but couldn't believe it would really be like this. Thanks, now I understand why using dir is better for my case. @ aschipfl: It only returns the 2 files IMG_0002.JPG & IMG_0013.JPG – Kevin Pullsoft Oct 13 '20 at 18:50
  • @KevinPullsoft, you had received three answers at the time you posted your comment above. Please review them and provide necessary feedback. People have taken time out of their day to provide you with specific assistance, and it seems rude to just ignore those efforts, made on your behalf! – Compo Oct 13 '20 at 19:40
  • Will do. And I was using @Squashman's solution which does work and answered the question, so I would mark it as the accepted answer if you would put your comment into an answer. – Kevin Pullsoft Oct 14 '20 at 17:16

2 Answers2

0

I'm assuming that you don't know what the actual numeric sequence is, and that there may be other IMG_*.JPG files which may have a different number of consecutive digits which should be left alone.

Here therefore is a simple example, which performs a directory listing of all files in the current directory matching the glob IMG_*.JPG, and pipes those through a findstr.exe match looking for names case insensitively matching IMG_ followed by exactly four digits and ending case insensitively with .JPG. Those are then passed through a to split each returned filename into two tokens, delimited with an underscore. The first token will be everything before the first delimiter, and the second, everything after the first delimiter. The Rename is them performed by joining the two tokens back together again with a _1 separator.

@Echo Off
SetLocal EnableExtensions
For /F "Delims=" %%G In ('Dir /B /A:-D "IMG_*.JPG" ^
 ^| "%SystemRoot%\System32\findstr.exe" ^
 /IR "^IMG_[0123456789][0123456789][0123456789][0123456789]\.JPG$"'
) Do For /F "Tokens=1,* Delims=_" %%H In ("%%G"
) Do Ren "%%G" "%%H_1%%~nI%%~xG"

The above is actually a single line command, split over several for easy reading, so you could use it in one line and run it against the current directory directly in :

For /F Delims^= %G In ('Dir /B/A-D "IMG_*.JPG"^|%SystemRoot%\System32\findstr.exe /IR "^IMG_[0123456789][0123456789][0123456789][0123456789]\.JPG$"')Do @For /F "Tokens=1* Delims=_" %H In ("%G")Do @Ren "%G" "%H_1%~nI%~xG"
Compo
  • 36,585
  • 5
  • 27
  • 39
  • I appreciate the elaborate answer, but it does much more than what I needed. I might even have a use for it in the future, but to answer the initial question - converting all "IMG_*.*" to "IMG_1*.*" - just a small modification to my script was needed. Thank you anyway – Kevin Pullsoft Oct 14 '20 at 17:26
  • It does not do more than is needed @KevinPullsoft. It does exactly what was requested, and does so in a way which will need no, or infrequent, modification. If you run this in any directory containing `IMG_*.jpg` files it will rename every one of those containing exactly four digits, to include a leading `1`. It does not need to know any of your filenames, and nothing needs hard coded. It will just do all of them. In fact my answer above, is an improved method of both your provided code and the initial comment by Squashman, which both unnecessarily use `call` commands. – Compo Oct 14 '20 at 18:02
-3

I'd consider using the /a parameter with SET, and then you can simply add 1 to the number, or get the actual number after the _, then add a digit to the end of it. It might make your files more readable.

LarryF
  • 4,925
  • 4
  • 32
  • 40