Skip to main content

bulkRename v2.0 released

Tags:
Reading time: 3 minutes Suggest an edit

I've converted my bulk file renaming utility from VB.NET to C# and made use of a command line arguments parsing library so that it will accept folders and regex patterns with spaces in them. It behaves a bit weird if you don't encapsulate your arguments in quotation marks (") or if you forgo the use of an equals sign (=) between the parameter flag and its argument, but those are small concessions to make.

The source is below:

/***
* Title: bulkRename
* Author: haliphax
* Version: 2.0
* Date: 2011/11/29
* Description:
* Rename files in bulk given a root folder, a regex to compare
* against for filename matches, and a new naming convention which
* can use group references from the filename regex.
***/


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using CommandLine.Utility;

namespace bulkRename
{
class Program
{
static void Main(string[] args)
{
// parse command line arguments
Arguments cmd = new Arguments(args);
// "letterhead"
Console.Out.WriteLine("\nbulkRename v2.0 by haliphax - 2011/11/29");
Console.Out.WriteLine("=========================================");
// grab root dir
String root = Environment.CurrentDirectory;
if(cmd["r"] != null)
root = cmd["r"];

// validate parameters
if(root == null || cmd["c"] == null || cmd["n"] == null)
{
// get my filename
string cmdFileName = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
cmdFileName = cmdFileName.Substring(cmdFileName.LastIndexOf('\\') + 1);
// show syntax
Console.Out.WriteLine("Syntax: " + cmdFileName + " [-r=\"\"] [-t] -c=\"\" -n=\"\"");
Console.Out.WriteLine("Options:");
Console.Out.WriteLine(" -r ==> Folder to search [OPTIONAL]");
Console.Out.WriteLine(" -t ==> Test only (do not rename) [OPTIONAL]");
Console.Out.WriteLine(" -c ==> Current naming convention (regex pattern)");
Console.Out.WriteLine(" -n ==> New naming convention (regex pattern)");
Console.Out.WriteLine("NOTE: The quotation marks are important!");
return;
}

// test regex for flaws
try
{
Regex.Match("", cmd["c"]);
}
catch(Exception ex)
{
Console.Out.WriteLine("Error: " + ex.Message);
return;
}

// trim root if it has a trailing backslash
if(root.EndsWith("\\"))
root = root.Substring(0, root.Length - 1);

// load files in root folder
string[] files = null;

// attempt to grab list of files
try
{
files = System.IO.Directory.GetFiles(root);
}
catch(Exception ex)
{
Console.Out.WriteLine("Error: " + ex.Message);
return;
}

if(cmd["t"] != null)
Console.Out.WriteLine("*** TEST ONLY, WILL NOT RENAME ***");
int counter = 0;
Boolean errors = false;
Console.Out.WriteLine("* Root Folder: " + root);

// iterate through file list and check for matches
foreach(String fileName in files)
{
// file matches regex for current convention
if(! Regex.Match(fileName, cmd["c"]).Success)
continue;
// build new file name and output renaming action
String newFileName = Regex.Replace(fileName, cmd["c"], cmd["n"],
RegexOptions.Singleline);
String displayName = fileName.Substring(root.Length + 1);
String newDisplayName = newFileName.Substring(root.Length + 1);
Console.Out.WriteLine(displayName + " ==> " + newDisplayName);

// actually rename if not in test mode
if(cmd["t"] == null)
{
try
{
System.IO.File.Move(fileName, newFileName);
counter++;
}
catch(Exception ex)
{
Console.Out.WriteLine("Error: " + ex.Message);
errors = true;
}
}
}

// summary
if(cmd["t"] == null)
Console.Out.WriteLine("* Files renamed: " + counter);
if(errors)
Console.Out.WriteLine("NOTE: There were errors encountered while processing the batch");
}
}
}