Rename substring of filename based on partial filename match in same folder

.net frameworkbatchcmd.exeregexvbscript

I have a folder full of files (.avi and .txt files):

'MyVideo1-MyEncode.avi'
'MyVideo1.avi 16-05-2019 15-41-01.txt'

'My Video 2.avi'
'My Video 2.avi 16-05-2019 16-43-11.txt'

'My Video 3 [Summer]-MyEncode.avi'
'My Video 3 [Summer].avi 16-05-2019 17-57-24.txt'

'My Video 4-(Fall).avi'
'My Video 4-(Fall).avi 13-05-2019 19-29-16.txt'

'My Video 5-(Winter)-MyEncode.avi'
'My Video 5-(Winter).avi 11-05-2019 11-15-05.txt'

If the .avi file includes "-MyEncode" in the filename, I would like to then copy this part of the string into the filename of the corresponding text file.

e.g.

"MyVideo1-MyEncode.avi" includes the text "-MyEncode" in the filename

so:
"MyVideo1.avi 16-05-2019 15-41-01.txt"

should be renamed as:
"MyVideo1-MyEncode.avi 16-05-2019 15-41-01.txt"

on the other hand:

"My Video 2.avi" does not contain the string "-MyEncode" so the corresponding .txt file should not be renamed.

I have a number of folders containing files like this.

I am thinking I need to run the cmd line or batch file for something like:

for /R %x in (*.avi) do ren "%x" *.txt

however this does not account for the partial filename match.

Can anyone please help?

PS – If I makes things easier, I can rename the like of "My Video 3 [Summer]-MyEncode.avi" to "My_Video_3_[Summer]-MyEncode.avi" (i.e. to remove the spaces)

Best Answer

This ended up being a hot-mess for me since the -MyEncode gets put in the middle of the file name, but this is what I came up with and it works based on the information you've provided:

@echo off

set "dir=C:\Your\Directory"
set "enc=-MyEncode"

setlocal EnableDelayedExpansion
for /r "%dir%" %%A in ("*%enc%*.avi") do (
    set "sub=%%~nxA"
    set "name=!sub:~0,-13!"
    for /r "%dir%" %%B in ("*!name!*.txt") do (
        set "txt=%%~nxB"
        set "num=!txt:~-24!"
        set "fin=!name!!enc!.avi!num!"
        if not !txt!==!fin! ren "%dir%\!txt!" "!fin!"
    )
)
endlocal

For starters, setlocal EnableDelayedExpansion is required since we're dealing with variables used throughout our nested for-loop. These variables are used to make things a bit easier to digest and to change when you go back and edit, so up front I've set variables for both the directory in which the files are located (dir) and for the string you want to insert into your filenames (enc).

The initial for-loop checks the directory for all instances of .avi files that contain the string -MyEncode, and for each instance/iteration a parameter %%A is returned and used to do a few other commands. The first command in the initial loop sets a variable (sub) with the filename (n) and extension (x) of our %%A parameter - this cuts off all of the directory information since we won't need it. The second command uses our new sub variable to set a newer variable (name) that subtracts the last 13 characters from the filename (the last 13 being -MyEncode.avi) so we can use it for the next part: the nested for-loop.

Like the initial for-loop, our nested one looks in our directory - but instead of looking for .avi files containing our enc variable, it looks for .txt files containing our new name variable. The first command while setting the txt variable is to reduce %%B to its filename and extension, then we set a num variable that reduces the txt variable to its last 24 characters (the numbers and spaces at the end). Finally, it sets the variable fin to what we want the new text file to be called: !name!!enc!.avi!num! - this is the name established in the initial for-loop with -MyEncode added to it, a .avi added to that, then the numbers that were originally at the end. From here, we use an if not command to say that: for all txt variables that are not already equal to their fin counterparts, rename the txt to fin. I use if not here because the text files that have already been changed to reflect their corresponding .avi files don't need to be renamed again.

Hopefully this helps!

Related Question