Click here to Skip to main content
15,867,308 members
Articles / Programming Languages / C#
Article

FileRen - Batch File Renamer

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

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:

C#
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:

C#
/// <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);
            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.

C#
// 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.,

C#
/// <summary>
/// Type for handling the renaming part options
/// </summary>
public enum RenamingOptions
{
    /// <summary>
    /// Renames the name part of file-name
    /// </summary>
    RenameNameOnly,
    /// <summary>
    /// Renames the extension only
    /// </summary>
    RenameExtOnly,
    /// <summary>
    /// Renames whole name
    /// </summary>
    RenameWholeName,
    /// <summary>
    /// Renaming starts from specified position
    /// </summary>
    RenameCustom
}

/// <summary>
/// Type for handling the pattern options
/// </summary>
public enum PatternOptions
{
    /// <summary>
    /// Lower-case pattern
    /// </summary>
    PatternLowerCase,
    /// <summary>
    /// Upper-case pattern
    /// </summary>
    PatternUpperCase,
    /// <summary>
    /// Init-cap pattern
    /// </summary>
    PatternInitCap,
    /// <summary>
    /// Random case pattern
    /// </summary>
    PatternRandomCase,
    /// <summary>
    /// Invert case pattern
    /// </summary>
    PatternInvertCase,
    /// <summary>
    /// No changes to the name
    /// </summary>
    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.

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

License

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


Written By
Software Developer (Senior)
India India
I: working as software engineer.
My Blog: http://blog.abstractcomputing.in

Comments and Discussions

 
QuestionRealy a nice work。I wonder if i have any permission to translate it to Simple-Chinese Pin
xcf00715-Oct-12 15:13
xcf00715-Oct-12 15:13 
QuestionRenaming Pin
cometo_raj13-Jun-12 19:27
cometo_raj13-Jun-12 19:27 
GeneralSandbar Pin
David!26-Nov-07 16:29
David!26-Nov-07 16:29 
AnswerRe: Sandbar Pin
A. Bhandari a.k.a Amit Bhandari26-Nov-07 22:46
A. Bhandari a.k.a Amit Bhandari26-Nov-07 22:46 
GeneralThreading, resources, sleeping and polling Pin
Leo Davidson27-Feb-07 6:49
Leo Davidson27-Feb-07 6:49 
AnswerRe: Threading, resources, sleeping and polling Pin
A. Bhandari a.k.a Amit Bhandari1-Mar-07 18:30
A. Bhandari a.k.a Amit Bhandari1-Mar-07 18:30 
GeneralRe: Threading, resources, sleeping and polling Pin
Saltire5-Mar-07 23:00
Saltire5-Mar-07 23: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.