Click here to Skip to main content
15,125,756 members
Articles / Programming Languages / C#
Posted 27 Feb 2007


22 bookmarked

FileRen - Batch File Renamer

Rate me:
Please Sign up or sign in to vote.
3.40/5 (7 votes)
27 Feb 2007LGPL33 min read
Batch file renaming utility using threading
Screenshot - fileren.gif


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.


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:

/// <summary>
/// Generates the new name based on the pattern properties
/// set.
/// </summary>
/// <param name="fileNameToBeProcessed">Original name</param>
/// <param name="newFileName">[Out] New file name</param>
/// <returns>true if successful, false otherwise</returns>
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);
        case RenamingOptions.RenameExtOnly:
            fileName = Path.GetExtension(fileNameToBeProcessed).Substring(1);
        case RenamingOptions.RenameWholeName:
            fileName = fileNameToBeProcessed;
        case RenamingOptions.RenameCustom:
            fileName = Path.GetFileName(fileNameToBeProcessed).Substring
            (_splitPositionToBeRenamed - 1);

    switch( TextPatternToBeUsed )
        case PatternOptions.PatternLowerCase: 
            fileName = fileName.ToLower();
        case PatternOptions.PatternUpperCase: 
            fileName = fileName.ToUpper();
        case PatternOptions.PatternInitCap: 
            fileName = StringFunctionality.Initcaps(fileName); 
        case PatternOptions.PatternRandomCase: 
            fileName = StringFunctionality.RandomCase(fileName); 
        case PatternOptions.PatternInvertCase: 
            fileName = StringFunctionality.InvertStringCase(fileName); 

    if (_replaceStringWithExpression)
        fileName = fileName.Replace(_stringToFindForReplace, 

    if (_insertStringToFileName)
        if (_renameWhichPart != RenamingOptions.RenameExtOnly)
            tempFileName = fileNameToBeProcessed.Substring(0, 
                fileNameToBeProcessed.Length - 

            if(_positionStringToBeAppended < tempFileName.Length)
                fileName = tempFileName.Insert(_positionStringToBeAppended, 
                StringBuilder sbdr = new StringBuilder(tempFileName);
                for(i = tempFileName.Length; 
            i < _positionStringToBeAppended; i++)
                    sbdr.Append(" ");
                tempFileName = sbdr.ToString();
                fileName = tempFileName.Insert(_positionStringToBeAppended, 

    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; 
        case RenamingOptions.RenameNameOnly: newFileName = fileName + 
        case RenamingOptions.RenameExtOnly: 
            newFileName = Path.GetFileName(fileNameToBeProcessed).Substring(0, 
            - fileName.Length) + fileName;
        case RenamingOptions.RenameCustom: newFileName = 
            fileNameToBeProcessed.Substring(0, _splitPositionToBeRenamed - 1) + fileName; 

    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 members of Settings class
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.,

/// <summary>
/// Type for handling the renaming part options
/// </summary>
public enum RenamingOptions
    /// <summary>
    /// Renames the name part of file-name
    /// </summary>
    /// <summary>
    /// Renames the extension only
    /// </summary>
    /// <summary>
    /// Renames whole name
    /// </summary>
    /// <summary>
    /// Renaming starts from specified position
    /// </summary>

/// <summary>
/// Type for handling the pattern options
/// </summary>
public enum PatternOptions
    /// <summary>
    /// Lower-case pattern
    /// </summary>
    /// <summary>
    /// Upper-case pattern
    /// </summary>
    /// <summary>
    /// Init-cap pattern
    /// </summary>
    /// <summary>
    /// Random case pattern
    /// </summary>
    /// <summary>
    /// Invert case pattern
    /// </summary>
    /// <summary>
    /// No changes to the name
    /// </summary>

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.

Settings screen

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 [].

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.


  • v0.1.010 First initial release
  • v0.2.030 Beta release


This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


About the Author

A. Bhandari a.k.a Amit Bhandari
Software Developer (Senior)
India India
I: working as software engineer.
My Blog:

Comments and Discussions

QuestionRealy a nice work。I wonder if i have any permission to translate it to Simple-Chinese Pin
xcf00715-Oct-12 16:13
Memberxcf00715-Oct-12 16:13 
QuestionRenaming Pin
cometo_raj13-Jun-12 20:27
Membercometo_raj13-Jun-12 20:27 
GeneralSandbar Pin
David!26-Nov-07 17:29
MemberDavid!26-Nov-07 17:29 
AnswerRe: Sandbar Pin
A. Bhandari a.k.a Amit Bhandari26-Nov-07 23:46
MemberA. Bhandari a.k.a Amit Bhandari26-Nov-07 23:46 
GeneralThreading, resources, sleeping and polling Pin
Leo Davidson27-Feb-07 7:49
MemberLeo Davidson27-Feb-07 7:49 
You mention that the program uses multi-threading and thus consumes fewer resources.

I may have missed something in the code but it looks like the program creates a thread to list the directory and then waits for it to finish, using a timer to poll the other thread's status.

This has no effect on resource usage. It is good because it means the user interface is not locked up while the directory is listed, but it does not decrease resource usage. (In fact, it increases it slightly, but the tiny increase is worth it for the benefit of a non-blocked UI thread.)

There is also only ever one filesystem thread so the directory listing itself is not done in a multithreaded way, although the program is multithreaded (it has a UI thread and a filesystem thread). This is actually a good thing as you'd probably get very bad performance, at least on a harddisk or CD-ROM, by reading directories using more than one thread.

The Sleep(10) calls in FormBase.cs worry me. You should never sleep in a UI thread and there are rarely good reasons to call Sleep anywhere at all. I couldn't see why these Sleep calls were there.

The Timer is also a bad idea since the UI thread is polling the filesystem thread to see if it has finished yet. Instead of polling you should add an event to the filesystem class which the form can add a handler to. When the filesystem class is done it calls the form's handler and the form is notified at the exact moment that the work is done, without wasting system resources by asking if the job is done every few seconds. C# makes events very easy to use and they are well worth learning about.

AnswerRe: Threading, resources, sleeping and polling Pin
A. Bhandari a.k.a Amit Bhandari1-Mar-07 19:30
MemberA. Bhandari a.k.a Amit Bhandari1-Mar-07 19:30 
GeneralRe: Threading, resources, sleeping and polling Pin
Saltire6-Mar-07 0:00
MemberSaltire6-Mar-07 0:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.