Introduction
I wonder why in this era of free open-source, there are still small utilities that are considered as proprietary software which otherwise should not be. One of the examples is Batch File Renaming utility. You can always find one freeware application on renaming file(s) in batch mode but the source code alongwith is less likely. So, I come forward to present how it can be done with this code snippet. I would like to mention that this is just a beginning to the approach and would likely be containing bugs, but my commitment is sincere and I will try to remove all those bugs as and when they are identified.
The file-renamer is yet another implementation of the batch file renaming utility. It uses multi-threading, first to collect file(s) and then to rename them so that the whole process consumes less resources of the system.
Background
The idea came to my mind when I studied the code of CoolFileSystem
available here at coolfilesystemclass.asp which uses multi-threading to collect files in an ArrayList
.
It uses the CoolFileSystem
implementation by Vahe Karamian which is code present on CodeProject only.
Using the code
As proper comments have been added to the code to make it easy to understand, I am not giving any description of the code here. Still, let us analyze the basic structure of some useful classes in FileRen
.
The FileRen
uses CoolFileSystem
to collect files in an ArrayList
and then renames the file(s) based on the pattern selected by the user to rename the file(s). The pattern options are limited right now, but I am planning to include Regular Expressions based renaming options.
The first class is the Startup
class, which associates all the exceptions in the Application
to a locally defined procedure. The code is as follows:
Application.ThreadException += new ThreadExceptionEventHandler(ShowErrorBox);
The Settings
class is used to generate the new name of the file based on the pattern selected by the user. The code behind the generation of the new file name is:
public bool GetNewFileName(string fileNameToBeProcessed,
out string newFileName)
{
string fileName = "", tempFileName;
int i;
newFileName = "";
switch( RenameWhichPart )
{
case RenamingOptions.RenameNameOnly:
fileName = Path.GetFileName (fileNameToBeProcessed).Substring(0,
fileNameToBeProcessed.Length -
Path.GetExtension FileNameToBeProcessed).Length);
break;
case RenamingOptions.RenameExtOnly:
fileName = Path.GetExtension(fileNameToBeProcessed).Substring(1);
break;
case RenamingOptions.RenameWholeName:
fileName = fileNameToBeProcessed;
break;
case RenamingOptions.RenameCustom:
fileName = Path.GetFileName(fileNameToBeProcessed).Substring
(_splitPositionToBeRenamed - 1);
break;
}
switch( TextPatternToBeUsed )
{
case PatternOptions.PatternLowerCase:
fileName = fileName.ToLower();
break;
case PatternOptions.PatternUpperCase:
fileName = fileName.ToUpper();
break;
case PatternOptions.PatternInitCap:
fileName = StringFunctionality.Initcaps(fileName);
break;
case PatternOptions.PatternRandomCase:
fileName = StringFunctionality.RandomCase(fileName);
break;
case PatternOptions.PatternInvertCase:
fileName = StringFunctionality.InvertStringCase(fileName);
break;
}
if (_replaceStringWithExpression)
fileName = fileName.Replace(_stringToFindForReplace,
_stringToReplace);
if (_insertStringToFileName)
{
if (_renameWhichPart != RenamingOptions.RenameExtOnly)
{
tempFileName = fileNameToBeProcessed.Substring(0,
fileNameToBeProcessed.Length -
Path.GetExtension(fileNameToBeProcessed).Length);
if(_positionStringToBeAppended < tempFileName.Length)
fileName = tempFileName.Insert(_positionStringToBeAppended,
_stringToBeAppended);
else
{
StringBuilder sbdr = new StringBuilder(tempFileName);
for(i = tempFileName.Length;
i < _positionStringToBeAppended; i++)
sbdr.Append(" ");
tempFileName = sbdr.ToString();
fileName = tempFileName.Insert(_positionStringToBeAppended,
_stringToBeAppended);
}
}
}
if (_advancedControl)
{
if (_replaceSpaceWithUnderscore)
fileName = fileName.Replace(" ", "_");
if (_replaceUnderscoreWithSpace)
fileName = fileName.Replace("_", " ");
if (_killVowels)
fileName = StringFunctionality.KillVowels(fileName);
if (_killEndAndDoubleSpace)
{
fileName = fileName.Trim();
fileName = fileName.Replace(" ", "");
}
}
switch( RenameWhichPart )
{
case RenamingOptions.RenameWholeName: newFileName = fileName;
break;
case RenamingOptions.RenameNameOnly: newFileName = fileName +
Path.GetExtension(fileNameToBeProcessed);
break;
case RenamingOptions.RenameExtOnly:
newFileName = Path.GetFileName(fileNameToBeProcessed).Substring(0,
Path.GetFileName(fileNameToBeProcessed).Length
- fileName.Length) + fileName;
break;
case RenamingOptions.RenameCustom: newFileName =
fileNameToBeProcessed.Substring(0, _splitPositionToBeRenamed - 1) + fileName;
break;
}
return true;
}
As you might notice, the function generates a new name of the file, but this is based on some conditions which are encapsulated in if-else blocks. Let us analyze and drill down further into these conditions.
Let me first list the class members which are privately owned.
private bool _replacePrevFiles = false;
private bool _ignoreIllegalFiles = false;
private PatternOptions _textPatternToBeUsed = PatternOptions.PatternNone;
private RenamingOptions _renameWhichPart = RenamingOptions.RenameWholeName;
private int _splitPositionToBeRenamed = 0;
private bool _replaceStringWithExpression = false;
private string _stringToFindForReplace = "";
private string _stringToReplace = "";
private bool _insertStringToFileName = false;
private string _stringToBeAppended = "";
private int _positionStringToBeAppended = 0;
private bool _advancedControl = false;
private bool _replaceSpaceWithUnderscore = false;
private bool _replaceUnderscoreWithSpace = false;
private bool _killEndAndDoubleSpace = false;
private bool _killVowels = false;
Each of the above members are exposed to the outside world as public properties which can be configured by the GUI designed to modify the pattern. There are two enum types associated, viz.,
public enum RenamingOptions
{
RenameNameOnly,
RenameExtOnly,
RenameWholeName,
RenameCustom
}
public enum PatternOptions
{
PatternLowerCase,
PatternUpperCase,
PatternInitCap,
PatternRandomCase,
PatternInvertCase,
PatternNone
}
The renaming options are used to specify which part of the file name is to be used for processing and the pattern options are used to perform some processing to the text of the file name in order to generate the new file name.

As might be clear from the above screenshot, each property of the Setting
class is associated with one of the options displayed corresponding to it on the screen. Based on the selected options by the user, the corresponding variables are checked and a new file name is generated.
All string related processing is encapsulated in StringFunctionality
class. All members of this class are static
.
For a more recent download, you can visit my website [http://amitbhandari.co.nr].
Points of Interest
The whole process of string processing is done using the StringBuilder
object, however, String
objects are still used where there is no other option left.
In addition, the emphasis in all the further revisions of the code will be based on Regular Expressions since it will make the pattern for renaming to be more precise. Moreover, complex conversions/replacements in the original filename string can be carried out easily.
History
- v0.1.010 First initial release
- v0.2.030 Beta release