I am reorganizing my MP3 collection and found that I needed to rename a large quantity of files. Of course, there are many free utilities that allow this operation - and that can use MP3 tags in the process - but I thought that I might write one myself. Thanks to regular expressions, the task shouldn't be that hard. In fact, in a few minutes I came up with the following console application. As you see, most of the code is used to extract and validate arguments on the command line:
Imports
System.Text.RegularExpressions
Imports System.IO
Module
Renx
Function Main(ByVal args() As String) As Integer
Console.WriteLine("RENX (C) Francesco Balena / Code Architects Srl")
Dim recurse As Boolean = False
Dim renameMode As Boolean = False
Dim oldNamePattern As String = Nothing
Dim newNamePattern As String = Nothing
' analyze each argument
For Each arg As String In args
Select Case arg.ToLower()
Case "/s", "-s"
recurse = True
Case "/r", "-r"
renameMode = True
Case "/h", "-h"
Return ShowHelp(0)
Case Else
If oldNamePattern Is Nothing Then
oldNamePattern = "^" & arg & "$"
ElseIf newNamePattern Is Nothing Then
newNamePattern = arg
Else
Return ShowHelp(1)
End If
End Select
Next
' check that we have both mandatory arguments
If oldNamePattern Is Nothing OrElse newNamePattern Is Nothing Then
Return ShowHelp(1)
End If
' create the regex and check that pattern syntax is ok
Dim reSearch As Regex
Try
reSearch = New Regex(oldNamePattern, RegexOptions.IgnoreCase)
' test the replace pattern as well
Dim tmp As String = reSearch.Replace("a dummy string", newNamePattern)
Catch ex As Exception
Console.WriteLine("SYNTAX ERROR: {0}", ex.Message)
Return 3
End Try
Console.WriteLine()
' iterate over all files in current directory (and its subdirectories, if recurse mode)
Dim searchOpt As SearchOption = SearchOption.TopDirectoryOnly
If recurse Then searchOpt = SearchOption.AllDirectories
Dim parsedFilesCount As Integer = 0
Dim renamedFilesCount As Integer = 0
Dim errorsCount As Integer = 0
For Each oldFile As String In Directory.GetFiles(Directory.GetCurrentDirectory(), "*.*", searchOpt)
parsedFilesCount += 1
' the regex applies to name only
Dim oldName As String = Path.GetFileName(oldFile)
Dim ma As Match = reSearch.Match(oldName)
If ma.Success Then
' this is the new name
Dim newName As String = ma.Result(newNamePattern)
Console.WriteLine(oldFile)
Console.Write(" => {0}", newName)
renamedFilesCount += 1
' proceed with rename only if not in simulation mode
If renameMode Then
Try
Dim dirName As String = Path.GetDirectoryName(oldFile)
Dim newFile As String = Path.Combine(dirName, newName)
File.Move(oldFile, newFile)
Catch ex As Exception
Console.Write(" -- ERROR: {0}", ex.Message)
errorsCount += 1
End Try
End If
Console.WriteLine()
End If
Next
' Display a report
If renameMode Then
Console.WriteLine("Summary: {0} parsed files, {1} renamed files, {2} errors", parsedFilesCount, renamedFilesCount, errorsCount)
Else
Console.WriteLine("Summary: {0} parsed files, {1} files affected", parsedFilesCount, renamedFilesCount)
Console.WriteLine()
Console.WriteLine("NOTE: Running in simulation mode. Specify the /R option to actually rename files.")
End If
' Return an error code
If errorsCount = 0 Then
Return 0
Else
Return 2
End If
End Function
Function ShowHelp(ByVal exitCode As Integer) As Integer
Console.WriteLine()
Console.WriteLine("Syntax: RENX <oldnamepattern> <newnamepattern> [/R] [/S] [/H]")
Console.WriteLine(" oldnamepattern : regex that selects the files to be renamed")
Console.WriteLine(" newnamepattern : regex that specifies how files must be renamed")
Console.WriteLine(" /R : rename files")
Console.WriteLine(" /S : iterate over subdirectories")
Console.WriteLine(" /H : display this help")
Console.WriteLine("NOTE: By default the program runs in simulation mode, and just displays how files would be renamed.")
Console.WriteLine(" You must specify the /R option to actually rename the files.")
Return exitCode
End Function
End
Module
At the very minimum, the RENX utility requires two arguments: a regex that specifies which files in the current directory (and its subdirectories, if you add the /S option) must be renamed, and a second regex that specifies how to rename the files that are matched by the first regex. The power of RENX is the fact that the first regex can (actually, must) specify one or more groups of characters, and these groups are then referenced in the second regex. For example, let's suppose that I have a folder with the following files:
01 Speak to Me.mp3
02 On the Run.mp3
03 Time.mp3
04 The Great Gig in the Sky.vb3
05 Money.mp3
06 Us and Them.mp3
07 Any Colour You Like.vbr
08 Brain Damage.mp3
09 Eclipse.vb3
and that I want to rename them as follows:
01 - Speak to Me - The Dark Side of the Moon.mp3
02 - On the Run - The Dark Side of the Moon.mp3
03 - Time - The Dark Side of the Moon.mp3
04 - The Great Gig in the Sky - The Dark Side of the Moon.vbr
05 - Money - The Dark Side of the Moon.mp3
06 - Us and Them - The Dark Side of the Moon.mp3
07 - Any Colour You Like - The Dark Side of the Moon.vb3
08 - Brain Damage - The Dark Side of the Moon.mp3
09 - Eclipse - The Dark Side of the Moon.vbr
Here's the RENX command that does it:
RENX "(\d\d) (.+?)(\..+)" "${1} - ${2} - The Dark Side of the Moon.${3}"
Notice that the first regex creates three groups by enclosing them in parenthesis: (\d\d) matches the song number, (.+?) matches the song title, and (\..+) matches the file extension, dot included. The second argument can then reorder these three groups, using the ${N}, where N is the position of the group as specified in the first regex. It is therefore to insert a dash after the song number, and the albumname after the song title.
Because the RENX utility is quite dangerous, by default it doe NOT rename the files, and it just lists how files would be renamed. To actually proceed with the rename operation, you must specify the /R option:
RENX "(\d\d) (.+?)(\..+)" "${1} - ${2} - The Dark Side of the Moon${3}" /R
That's all. You can play with the source code to extend the RENX utility as you prefer, and maybe turn it into a Windows Form application, or you can download the binary version from this link: Renx.zip (5.51 KB)