0

If possible, I am hoping to create a batch file that can go through a folder filled with seemingly random filenames and rename them using a substring that exists within each filename. The naming convention seems pretty random but within each file name exists an "a" followed by 2 digits then a "b" followed by 2 digits (a##b##). None of the values would match so you need not worry about resulting filenames conflicting with each other.

before:
left.process.a11b22.Feb.11
maid island a22b33 Mar 12
charm.dinner.a12b34.Jun.13
motivation blame a00b00 Nov 14
laser.activate.a99b99.Oct.15

I would just like these renamed to something more manageable for consistency while retaining the relevant values. Ideally, renaming them to the folder's name followed by the substring.

Ideal result:
Folder Name a00b00
Folder Name a11b22
Folder Name a12b34
Folder Name a22b33
Folder Name a99b99

This is asking a lot already and this isn't as important but if it could be done recursively that would save an extra step. Maybe even ignoring any file that doesn't have the substring in its name. However I've never managed to come across a batch that could recursively rename taking each individual Folder Name into account. Anyway, thanks in advance.

  • So it looks like your substring is always the third part of the file name that is delimited by a space or period. – Squashman Feb 01 '18 at 23:56
  • No, I just came up with random examples. Its always somewhere in the middle but it isn't always third from the beginning or second/third from the end. This is why it is so tricky. I am not even sure my request is possible but there are smarter people out there than me so I thought I would ask. – Daniel Sachs Feb 02 '18 at 00:10
  • It is possible. Dave Benham wrote a hybrid batch file named JRename. He maintains the code on DosTips.com forum. – Squashman Feb 02 '18 at 00:17

1 Answers1

0

I hope this is what you are looking for:

@ECHO OFF
SETLOCAL EnableDelayedExpansion



REM **************************************************

REM Source directory
SET source=C:\adjust\path

REM **************************************************



FOR /R "%source%" %%G IN ("*a??b??*") DO (
    SET "file_name=%%~nG"
    SET "counter=0"
    SET "error=0"
    ECHO !file_name! | FINDSTR /B /R "a[0-9][0-9]b[0-9][0-9]" >nul || CALL :get_file_name
    ECHO !file_name! | FINDSTR /I /B /R "a[0-9][0-9]b[0-9][0-9]" >nul && FOR %%H IN ("%%~dpG.") DO (SET "folder_name=%%~nxH") && REN "%%G" "!folder_name! - !file_name!%%~xG"
    IF "%error%"=="1" (ECHO Error: Cannot rename %%G^^!) ELSE (ECHO !folder_name! - !file_name!%%~xG)
)

ECHO Done^^!
PAUSE
EXIT


:get_file_name
IF !counter! LSS 10 (SET /A "counter=!counter!+1") ELSE (SET "error=1" & EXIT /B)
SET file_name=!file_name:*a=a!
ECHO !file_name! | FINDSTR /B /R "a[0-9][0-9]b[0-9][0-9]" >nul || SET file_name=!file_name:~1! || GOTO get_file_name
SET file_name=!file_name:~0,6!
EXIT /B

Each file that matches the a[0-9][0-9]b[0-9][0-9] scheme is getting renamed to folder_name - a[0-9][0-9]b[0-9][0-9] (if you do not want the - simply adjust the REN command).


For case-sensitive renaming of a??b??, A??b??, A??B?? and a??B?? scheme:

@ECHO OFF
SETLOCAL EnableDelayedExpansion



REM **************************************************

REM Source directory
SET source=C:\adjust\path

REM **************************************************



FOR /R "%source%" %%G IN ("*a??b??*") DO (
    SET "file_name=%%~nG"
    SET "counter=0"
    SET "error=0"
    ECHO !file_name! | FINDSTR /R "a[0-9][0-9]b[0-9][0-9] a[0-9][0-9]B[0-9][0-9]" >nul && CALL :small_a
    ECHO !file_name! | FINDSTR /R "A[0-9][0-9]b[0-9][0-9] A[0-9][0-9]B[0-9][0-9]" >nul && CALL :capital_a
    ECHO !file_name! | FINDSTR /I /B /R "a[0-9][0-9]b[0-9][0-9]" >nul && FOR %%H IN ("%%~dpG.") DO (SET "folder_name=%%~nxH") && REN "%%G" "!folder_name! - !file_name!%%~xG"
    IF "%error%"=="1" (ECHO Error: Cannot rename %%G^^!) ELSE (ECHO !folder_name! - !file_name!%%~xG)
)

ECHO Done^^!
PAUSE
EXIT


:small_a
IF !counter! LSS 10 (SET /A "counter=!counter!+1") ELSE (SET "error=1" & EXIT /B)
SET file_name=!file_name:*a=a!
ECHO !file_name! | FINDSTR /I /B /R "a[0-9][0-9]b[0-9][0-9]" >nul || SET file_name=!file_name:~1! || GOTO small_a
SET file_name=!file_name:~0,6!
EXIT /B

:capital_a
IF !counter! LSS 10 (SET /A "counter=!counter!+1") ELSE (SET "error=1" & EXIT /B)
SET file_name=!file_name:*A=A!
ECHO !file_name! | FINDSTR /I /B /R "A[0-9][0-9]b[0-9][0-9]" >nul || SET file_name=!file_name:~1! || GOTO capital_a
SET file_name=!file_name:~0,6!
EXIT /B

This shouldn't take much longer than the first solution.


Edit:

02/02/18:

Should be faster now. Thanks @Squashman!

03/02/18:

Added case-sensitive renaming, error and success output and counter to prevent endless loop.

05/02/18:

Fixed variable edit.


If you want to use another scheme simply adjust the Variable Edit, FINDSTR and/or Substring bit.

FatalBulletHit
  • 762
  • 6
  • 22
  • Real easy to get the parent folder name if you just do this. `FOR %%H IN ("%%~dpG.") DO set "parent=%%~nxH"` – Squashman Feb 02 '18 at 03:55
  • Dang, this worked perfectly. I am also sure I can adjust it to fit my needs in other circumstances as well. There are definitely parts that go over my head but good work. – Daniel Sachs Feb 02 '18 at 04:43
  • Glad I could help! If you are intrested in the way this works you might want to risk a look on this: [Variables: extract part of a variable (substring)](https://ss64.com/nt/syntax-substring.html), ["FOR" variable references](https://stackoverflow.com/questions/5034076/what-does-dp0-mean-and-how-does-it-work/5034119#5034119), [FINDSTR](https://ss64.com/nt/findstr.html) and [Redirection/Pipes](https://ss64.com/nt/syntax-redirection.html)! :) – FatalBulletHit Feb 02 '18 at 12:59
  • Definitely appreciate the effort from both of you. They newest version of the batch that you have up wasn't working for me. I played around with it looking at the edit history and couldn't get it to work until I changed the line SET file_name=!file_name:*a=a! back to SET file_name=!file_name:~1! I am not sure what these lines mean but it seems to work. – Daniel Sachs Feb 03 '18 at 03:16
  • I just discovered that sometimes in these sub-directories it will be inconsistent on whether or not it uses a##b## or a capitalized version (A##B##) and the batch will just sort of hang. Is there a way of going through where it isn't case sensitive? or it somehow renaming all the capital versions to lowercase? – Daniel Sachs Feb 03 '18 at 04:09
  • @DanielSachs Yep, there is, added it! :) – FatalBulletHit Feb 03 '18 at 15:44
  • @DanielSachs `SET file_name=!file_name:*a=a!` replaces every character in the variable `file_name` before `a` (because of the wildcard `*`) and `a` itself with `a` ([read more](https://ss64.com/nt/syntax-replace.html)). And `SET file_name=!file_name:~1!` removes the first character of the variable `file_name` ([read more](https://ss64.com/nt/syntax-substring.html)). – FatalBulletHit Feb 03 '18 at 19:31
  • I feel like I just continue to pester but when you explained to me how the `*a=a!` functioned, it made sense to me as to why it wouldnt work. I even tested it to see if it was the case. It wouldn't work with files that had another "a" in front of the "a##b##'. So it would work if the file was something like `dog.a00b00.dog` but not `cat.a00b00.cat`. I was hoping the solution would be something as simple as `*a??b=a??b!` but after skimming through the links you provided, that didnt seem to be possible. As a simple solution I just changed it `*a0=a0!` because the first number is usually a zero. – Daniel Sachs Feb 05 '18 at 04:57
  • and then if I need to I could just create another batch that has `*a1=a1!` etc. to go bad and fixs the others. – Daniel Sachs Feb 05 '18 at 04:58
  • @DanielSachs Yeah, thinking error (it was removing `*a` but replacing it with `a` again, so when checking again, it'd basically remove `a` and replace it with `a`). Fixed it, it will just remove the first character if `FINDSTR` cannot find `a??b??` at the beginning and then do the `*a=a` bit again! :) – FatalBulletHit Feb 05 '18 at 13:16
  • Still seem to be encountering the same issue. Maybe I wasn't explaining it correctly. What I assume is happening is this: `SET file_name=!file_name:*a=a!` Looks for the first "a" in the filename and erases everything before it. so `dog.a00b00` becomes `a00b00`. But this will get thrown off if there is another "a" before the intended substring. So a file like `cat.a00b00` will find that first "a" in cat and *a=a! will make it `at.a00b00`. The files won't actually get renamed but before the terminal would Echo `FolderName - at.a00b00`. After the last edit it will Echo `FolderName - t.a00b` – Daniel Sachs Feb 06 '18 at 20:43
  • @DanielSachs There is a loop you oversee: `SET file_name=!file_name:*a=a!` will output `at.a00b00`, `FINDSTR` will not find `a[0-9][0-9]b[0-9][0-9]` at the beginning, so it will `SET file_name=!file_name:~1!` (`t.a00b00`) and go back to `SET file_name=!file_name:*a=a!` which will now output `a00b00`. – FatalBulletHit Feb 07 '18 at 00:10