#region Author/About
/************************************************************************************
* VTDev - File Renamer Lite *
* *
* Created: October 10, 2010 *
* Built on: Win7 *
* Purpose: Simplified file renamer *
* Revision: 1.2 *
* Tested On: Win7 32bit *
* IDE: C# 2008 SP1 FW 3.5 *
* Referenced: VTD Freeware *
* Author: John Underhill (Steppenwolfe) *
* *
*************************************************************************************
You can not:
-Sell or redistribute this code or the binary for profit. This is freeware.
-Use this application, or portions of this code in spyware, malware, or any generally acknowledged form of malicious software.
-Remove or alter the above author accreditation, or this disclaimer.
You can:
-Use this code as a reference basis to build your own applications, (like ex. something far more comprehensive).
-Use portions of this code in your own projects or commercial applications.
I will not:
-Except any responsibility for this code whatsoever.
-Modify on demand.. you have the source code, read it, learn from it, write it.
-There is no guarantee of fitness, nor should you have any expectation of support.
-I further renounce any and all responsibilities for this code, in every way conceivable,
now, and for the rest of time.
-Changes to v1.1
-Added Case processing
-Added number removal option
-Fixed bug in multiple rule processing
-Added help facility
-Changes to 1.2
-Added save directory location
Cheers,
John
steppenwolfe_2000@yahoo.com
*/
#endregion
#region Directives
using System;
using System.Collections.Generic;
using System.Collections;
using System.Windows.Forms;
using System.IO;
using Microsoft.Win32;
using System.Globalization;
#endregion
namespace File_Renamer
{
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
public partial class frmMain : Form
{
#region Constants
private const int MAXFILES = 100000;
private const int MAXRULES = 20;
private const string SEPERATOR = "|$|";
private const string MEDIATYPES = @"Applications\wmplayer.exe\SupportedTypes";
#endregion
#region Enum
private enum ChangeState
{
Start,
Cancel,
Undo
}
#endregion
#region Delegates/Events
private delegate void TickDelegate(int count, string prompt);
private event TickDelegate Tick;
#endregion
#region Properties
private ChangeState State { get; set; }
private bool Cancel { get; set; }
private int Counter { get; set; }
private ArrayList Filters { get; set; }
#endregion
#region Fields
private HelpProvider _hpHelp;
#endregion
#region Controls
private void btnDirectory_Click(object sender, EventArgs e)
{
Reset();
using (FolderBrowserDialog fbFolder = new FolderBrowserDialog())
{
fbFolder.ShowNewFolderButton = false;
// startup path StartFolder
if (Properties.Settings.Default.InputPath.Length > 0)
{
fbFolder.SelectedPath = Properties.Settings.Default.InputPath;
}
if (fbFolder.ShowDialog() == DialogResult.OK)
{
txtDirectory.Text = fbFolder.SelectedPath;
Properties.Settings.Default.InputPath = txtDirectory.Text;
ssStatus.Items[0].Text = "Status: Folder Selected";
}
}
if (this.Filters.Count > 0)
{
btnStart.Enabled = true;
}
}
private void btnRuleAdd_Click(object sender, EventArgs e)
{
string rule = "";
// idiot proofing
if (lstRules.Items.Count > MAXRULES)
{
MessageBox.Show("You have exceeded the maximum of " + MAXRULES.ToString() + " rule changes. Rule will not be added.",
"Maximum rules exceeded", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
Reset();
if (cbRuleType.SelectedItem.ToString() == "Add")
{
if (txtRule.Text.Length > 0)
{
rule = cbRuleType.SelectedItem.ToString() + " '" + txtRule.Text + "' to " + cbRulePosition.SelectedItem.ToString();
this.Filters.Add(cbRuleType.SelectedItem.ToString() + SEPERATOR + txtRule.Text + SEPERATOR + cbRulePosition.SelectedItem.ToString());
}
}
else if (cbRuleType.SelectedItem.ToString() == "Remove")
{
if (txtRule.Text.Length > 0)
{
rule = cbRuleType.SelectedItem.ToString() + " '" + txtRule.Text + "' at " + cbRulePosition.SelectedItem.ToString();
this.Filters.Add(cbRuleType.SelectedItem.ToString() + SEPERATOR + txtRule.Text + SEPERATOR + cbRulePosition.SelectedItem.ToString());
}
}
else
{
if (txtRule.Text.Length > 0)
{
rule = cbRuleType.SelectedItem.ToString() + " '" + txtRule.Text + "' with '" + txtRule2.Text + "' at " + cbRulePosition.SelectedItem.ToString();
this.Filters.Add(cbRuleType.SelectedItem.ToString() + SEPERATOR + txtRule.Text + SEPERATOR + txtRule2.Text + SEPERATOR + cbRulePosition.SelectedItem.ToString());
}
}
if (rule.Length > 0)
{
lstRules.Items.Add(rule);
txtRule.Clear();
txtRule2.Clear();
if (IsValidDirectory(txtDirectory.Text))
{
btnStart.Enabled = true;
}
}
}
private void btnStart_Click(object sender, EventArgs e)
{
UpdateVisuals();
switch (this.State)
{
case ChangeState.Cancel:
CancelRename();
break;
case ChangeState.Start:
StartRename();
break;
case ChangeState.Undo:
UndoRename();
break;
}
}
private void btnRuleRemove_Click(object sender, EventArgs e)
{
if (lstRules.Items.Count > 0 && lstRules.SelectedItem != null)
{
this.Filters.RemoveAt(lstRules.SelectedIndex);
lstRules.Items.RemoveAt(lstRules.SelectedIndex);
}
if (lstRules.Items.Count == 0)
{
btnStart.Enabled = false;
}
}
private void cbFormat_SelectedIndexChanged(object sender, EventArgs e)
{
Reset();
}
private void cbRuleType_SelectedIndexChanged(object sender, EventArgs e)
{
// add
if (cbRuleType.SelectedIndex == 0)
{
lblRule.Visible = false;
txtRule2.Visible = false;
lblClause.Text = "to";
txtRule.Width = 196;
cbRulePosition.Items.Clear();
cbRulePosition.Items.Add("Start");
cbRulePosition.Items.Add("End");
cbRulePosition.SelectedIndex = 0;
}
// remove
else if (cbRuleType.SelectedIndex == 1)
{
lblRule.Visible = false;
txtRule2.Visible = false;
lblClause.Text = "at";
txtRule.Width = 196;
cbRulePosition.Items.Clear();
cbRulePosition.Items.Add("All");
cbRulePosition.Items.Add("Start");
cbRulePosition.Items.Add("End");
cbRulePosition.SelectedIndex = 0;
}
// replace
else if (cbRuleType.SelectedIndex == 2)
{
lblRule.Visible = true;
txtRule2.Visible = true;
txtRule.Width = 84;
lblClause.Text = "at";
cbRulePosition.Items.Clear();
cbRulePosition.Items.Add("All");
cbRulePosition.Items.Add("Start");
cbRulePosition.Items.Add("End");
cbRulePosition.SelectedIndex = 0;
}
}
public frmMain()
{
InitializeComponent();
}
private void frmMain_Load(object sender, EventArgs e)
{
this.Filters = new ArrayList();
cData.FileList = new ArrayList();
cData.ChangeList = new ArrayList();
this.Tick += new TickDelegate(Progress_Tick);
this.State = ChangeState.Start;;
PopulateControlFields();
HelpSetup();
}
private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
{
if (Properties.Settings.Default.InputPath.Length > 0)
{
Properties.Settings.Default.Save();
}
}
#endregion
#region Files
private void CalculateNames()
{
string oldPath = "";
string newPath = "";
string oldName = "";
string newName = "";
string prompt = "";
int count = 0;
FileInfo info = null;
ArrayList oldList = new ArrayList();
for (int i = 0; i < cData.FileList.Count; i++)
{
if (this.Cancel)
{
Reset();
ssStatus.Items[0].Text = "Status: Operation Canceled";
return;
}
oldPath = (string)cData.FileList[i];
info = new FileInfo(oldPath);
if (info.Exists && !info.IsReadOnly)
{
oldName = info.Name.Replace(info.Extension, "");
newName = FileNumber(oldName) + FileFilter(oldName);
if (newName.Length > 0)
{
newPath = info.Directory + @"\" + newName + info.Extension;
if (!String.Equals(newPath, oldPath))
{
// sync them
cData.ChangeList.Add(newPath);
oldList.Add(oldPath);
// update ui
count++;
prompt = "Calculating " + count.ToString() + " of " + cData.FileList.Count.ToString();
this.Tick(oldList.Count, prompt);
}
}
}
}
cData.FileList = oldList;
}
private string FileFilter(string fileName)
{
string newName = "";
string oldName = fileName;
string filterType = "";
string element = "";
string condition = "";
string[] action;
string[] sep = new string[1];
sep[0] = SEPERATOR;
foreach (string s in this.Filters)
{
try
{
action = s.Split(sep, StringSplitOptions.None);
filterType = action[0];
if (newName.Length > 0)
{
oldName = newName;
}
switch (filterType)
{
case "Add":
element = action[1];
condition = action[2];
newName = condition == "Start" ? element + oldName : oldName + element;
break;
case "Remove":
{
element = action[1];
condition = action[2];
if (oldName.Contains(element))
{
if (condition == "Start")
{
int pos = oldName.IndexOf(element);
newName = oldName.Remove(pos, element.Length);
}
else if (condition == "End")
{
int pos = oldName.LastIndexOf(element);
newName = oldName.Remove(pos, element.Length);
}
else
{
newName = oldName.Replace(element, "");
}
}
break;
}
case "Replace":
{
element = action[1];
if (fileName.Contains(element))
{
string element2 = action[2];
condition = action[3];
if (condition == "Start")
{
int pos = oldName.IndexOf(element);
oldName = oldName.Remove(pos, element.Length);
oldName = oldName.Insert(pos, element2);
newName = oldName;
}
else if (condition == "End")
{
int pos = oldName.LastIndexOf(element);
oldName.Remove(pos, element.Length);
oldName.Insert(pos, element2);
newName = oldName;
}
else
{
newName = oldName.Replace(element, element2);
}
}
break;
}
}
}
catch
{
if (this.Counter <= MAXFILES)
{
continue;
}
}
}
if (newName == "")
{
newName = fileName;
}
// remove numbers
if (chkRemoveNumbers.Checked)
{
RemoveNumbers(ref newName);
}
// case conversion
ProcessCase(ref newName);
return newName;
}
private string FileNumber(string fileName)
{
this.Counter++;
switch (cbFormat.SelectedIndex)
{
case 0:
return "";
case 1:
return txtPrefix.Text + this.Counter.ToString() + txtSuffix.Text;
case 2:
return txtPrefix.Text + this.Counter.ToString("00") + txtSuffix.Text;
case 3:
return txtPrefix.Text + this.Counter.ToString("000") + txtSuffix.Text;
case 4:
return txtPrefix.Text + this.Counter.ToString("0000") + txtSuffix.Text;
case 5:
return txtPrefix.Text + this.Counter.ToString("00000") + txtSuffix.Text;
case 6:
return txtPrefix.Text + this.Counter.ToString("000000") + txtSuffix.Text;
default:
return txtPrefix.Text + this.Counter.ToString() + txtSuffix.Text;
}
}
private ArrayList GetFiles(string dir)
{
ArrayList list = new ArrayList();
string pattern = "*" + cbFileType.Text;
SearchOption option = chkSubfolder.Checked ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
if (Directory.Exists(dir))
{
if (chkSubfolder.Checked)
{
list = GetFiles(dir, pattern);
}
else
{
try
{
string[] files = Directory.GetFiles(dir, pattern, SearchOption.TopDirectoryOnly);
foreach (string s in files)
{
list.Add(s);
}
}
catch { }
}
}
return list;
}
private ArrayList GetFiles(string root, string pattern)
{
Stack<string> dirs = new Stack<string>(20);
ArrayList list = new ArrayList();
string[] subDirs = new string[0];
string[] files = null;
dirs.Push(root);
while (dirs.Count > 0)
{
string currentDir = dirs.Pop();
try
{
subDirs = Directory.GetDirectories(currentDir);
}
catch (UnauthorizedAccessException e) { continue; }
catch (DirectoryNotFoundException e) { continue; }
catch { }
try
{
files = Directory.GetFiles(currentDir, pattern);
}
catch (UnauthorizedAccessException e) { continue; }
catch (DirectoryNotFoundException e) { continue; }
catch { }
foreach (string file in files)
{
list.Add(file);
}
foreach (string str in subDirs)
{
dirs.Push(str);
}
}
return list;
}
private ArrayList GetFileTypes()
{
// get supported media types, missing from hkcr
// Applications\wmplayer.exe\SupportedTypes
Array media = EnumValues(Registry.ClassesRoot, MEDIATYPES);
Array list = EnumKeys(Registry.ClassesRoot, "");
ArrayList res = new ArrayList();
foreach (string s in media)
{
if (s.StartsWith("."))
{
res.Add(s);
}
}
foreach (string s in list)
{
if (s.StartsWith("."))
{
if (!res.Contains(s))
{
res.Add(s);
}
}
}
return res;
}
private void RenameFiles()
{
string oldPath = "";
string newPath = "";
string prompt = "";
int count = 0;
if (cData.ChangeList.Count > 0)
{
for (int i = 0; i < cData.FileList.Count; i++)
{
if (this.Cancel)
{
Reset();
ssStatus.Items[0].Text = "Status: Operation Canceled";
return;
}
oldPath = cData.FileList[i].ToString();
newPath = cData.ChangeList[i].ToString();
count++;
prompt = "Renaming " + count.ToString() + " of " + cData.FileList.Count.ToString() + " files..";
this.Tick(count, prompt);
if (oldPath != newPath)
{
try
{
File.Move(oldPath, newPath);
}
catch
{
if (count <= cData.FileList.Count)
{
continue;
}
}
}
}
ssStatus.Items[0].Text = "File names have been changed..";
}
}
#endregion
#region Helpers
private void CancelRename()
{
this.Cancel = true;
}
private void HelpSetup()
{
_hpHelp = new HelpProvider();
_hpHelp.SetShowHelp(this.txtDirectory, true);
_hpHelp.SetHelpString(this.txtDirectory, "Enter the directory here, or browse to location.");
_hpHelp.SetShowHelp(this.chkSubfolder, true);
_hpHelp.SetHelpString(this.chkSubfolder, "Include sub directories in your file search.");
_hpHelp.SetShowHelp(this.cbFileType, true);
_hpHelp.SetHelpString(this.cbFileType, "Select the file extension for the type of file you want renamed.");
_hpHelp.SetShowHelp(this.cbRuleType, true);
_hpHelp.SetHelpString(this.cbRuleType, "Add, Remove or Replace text within the file name.");
_hpHelp.SetShowHelp(this.cbRulePosition, true);
_hpHelp.SetHelpString(this.cbRulePosition, "Apply this rule to the Start, End or to all occurences within the file name.");
_hpHelp.SetShowHelp(this.lstRules, true);
_hpHelp.SetHelpString(this.lstRules, "Rules in this list are executed in order, from top to bottom.");
_hpHelp.SetShowHelp(this.cbCapitalization, true);
_hpHelp.SetHelpString(this.cbCapitalization, "You can Ignore capitalization, convert to all uppercase, all lowercase letters, or capitalize the first letter of each word.");
_hpHelp.SetShowHelp(this.btnRuleAdd, true);
_hpHelp.SetHelpString(this.btnRuleAdd, "Add a new rule to the list.");
_hpHelp.SetShowHelp(this.btnRuleRemove, true);
_hpHelp.SetHelpString(this.btnRuleRemove, "Remove the highlighted rule from the list..");
_hpHelp.SetShowHelp(this.txtPrefix, true);
_hpHelp.SetHelpString(this.txtPrefix, "Add a prefix before the number sequence. Example: '01x'.");
_hpHelp.SetShowHelp(this.cbFormat, true);
_hpHelp.SetHelpString(this.cbFormat, "Choose the format of the number sequence. The default is 'No Number', or numbering is turned off.");
_hpHelp.SetShowHelp(this.txtSuffix, true);
_hpHelp.SetHelpString(this.txtSuffix, "Add a suffix to the number sequence. Example ' - '.");
_hpHelp.SetShowHelp(this.btnStart, true);
_hpHelp.SetHelpString(this.btnStart, "Depending on the running state, this button will 'Start' processing, 'Cancel' the operation, or 'Undo' any changes made in the last run.");
_hpHelp.SetShowHelp(this.chkRemoveNumbers, true);
_hpHelp.SetHelpString(this.chkRemoveNumbers, "Remove all existing numbers from the file name.");
}
private bool IsValidDirectory(string dir)
{
if (dir.Length > 2)
{
if (Directory.Exists(dir))
{
return true;
}
}
return false;
}
private void PopulateControlFields()
{
// Status
ssStatus.Items.Add("Status: Waiting");
ssStatus.Items.Add("");
// File Type
ArrayList list = GetFileTypes();
for (int i = 0; i < list.Count; i++)
{
cbFileType.Items.Add(list[i]);
}
cbFileType.Sorted = true;
int ind = cbFileType.FindString(".avi");
if (ind != 0)
{
cbFileType.SelectedIndex = ind;
}
// Rule Type
cbRuleType.Items.Add("Add");
cbRuleType.Items.Add("Remove");
cbRuleType.Items.Add("Replace");
cbRuleType.SelectedIndex = 0;
// Rule Position
cbRulePosition.Items.Clear();
cbRulePosition.Items.Add("Start");
cbRulePosition.Items.Add("End");
cbRulePosition.SelectedIndex = 0;
// Rules
lstRules.Items.Clear();
// Format
cbFormat.Items.Add("No Number");
cbFormat.Items.Add("1");
cbFormat.Items.Add("01");
cbFormat.Items.Add("001");
cbFormat.Items.Add("0001");
cbFormat.Items.Add("00001");
cbFormat.Items.Add("000001");
cbFormat.SelectedIndex = 0;
// Capitalization
cbCapitalization.Items.Add("Ignore Case");
cbCapitalization.Items.Add("All Lowercase");
cbCapitalization.Items.Add("All Uppercase");
cbCapitalization.Items.Add("Capitalize each word");
cbCapitalization.SelectedIndex = 0;
}
private void ProcessCase(ref string name)
{
if (string.IsNullOrEmpty(name))
{
return;
}
// lowercase
if (cbCapitalization.SelectedIndex == 1)
{
name = name.ToLower();
}
// uppercase
else if (cbCapitalization.SelectedIndex == 2)
{
name = name.ToUpper();
}
// each word
else if (cbCapitalization.SelectedIndex == 3)
{
string[] sp = new string[1];
string[] words = new string[1];
sp[0] = " ";
try
{
if (name.Contains(" "))
{
words = name.Split(sp, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < words.Length; i++)
{
string s = words[i].Substring(0, 1);
int n = 0;
if (!int.TryParse(s, out n))
{
s = s.ToUpper();
words[i] = s + words[i].Substring(1, words[i].Length - 1);
}
}
name = string.Join(" ", words);
}
else
{
string s = name.Substring(0, 1);
int n = 0;
if (!int.TryParse(s, out n))
{
name = s.ToUpper() + name.Substring(1, name.Length - 1);
}
}
}
catch { return; }
}
}
private void RemoveNumbers(ref string name)
{
string s = "";
int n = 0;
for (int i = 0; i < name.Length; i++)
{
s = name.Substring(i, 1);
if (int.TryParse(s, out n))
{
name = name.Remove(i, 1);
if (i > -1)
{
i--;
}
}
}
}
private void Reset()
{
ResetData();
this.State = ChangeState.Start;
UpdateVisuals();
}
private void ResetData()
{
cData.ChangeList.Clear();
cData.FileList.Clear();
cData.Confirm = false;
this.Counter = 0;
this.Cancel = false;
}
private void ResetProgress(bool visible)
{
prgProgress.Visible = visible;
prgProgress.Value = 0;
prgProgress.Maximum = 0;
}
private void StartRename()
{
if (IsValidDirectory(txtDirectory.Text))
{
// reset data
ResetData();
// get the file list
ssStatus.Items[0].Text = "Building file list..";
cData.FileList = GetFiles(txtDirectory.Text);
// no files found
if (cData.FileList.Count == 0)
{
MessageBox.Show("No matching files found, check path and extension paramaters.", "No matches",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
Reset();
}
else
{
// show progress bar
ResetProgress(true);
prgProgress.Maximum = cData.FileList.Count;
// construct new file names
CalculateNames();
// modal confirmation
frmConfirmation f = new frmConfirmation();
f.ShowDialog(this);
if (cData.Confirm)
{
// cancel mode
this.State = ChangeState.Cancel;
UpdateVisuals();
RenameFiles();
// undo mode
this.State = ChangeState.Undo;
UpdateVisuals();
}
else
{
Reset();
}
}
}
}
private void UndoRename()
{
// opt out
if (MessageBox.Show("Undo all file name changes?", "Undo Rename",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
{
return;
}
string oldPath = "";
string newPath = "";
string prompt = "";
int count = 0;
if (cData.ChangeList.Count > 0)
{
// show progress bar
ResetProgress(true);
prgProgress.Maximum = cData.ChangeList.Count;
for (int i = 0; i < cData.FileList.Count; i++)
{
oldPath = cData.FileList[i].ToString();
newPath = cData.ChangeList[i].ToString();
count++;
prompt = "Undo Rename: " + count.ToString() + " of " + cData.FileList.Count.ToString() + " files..";
this.Tick(count, prompt);
try
{
File.Move(newPath, oldPath);
}
catch
{
if (count <= cData.FileList.Count)
{
continue;
}
}
}
}
Reset();
}
private void UpdateVisuals()
{
if (IsValidDirectory(txtDirectory.Text) && this.Filters.Count > 0)
{
btnStart.Enabled = true;
}
else
{
btnStart.Enabled = false;
}
// hide progress bar
ResetProgress(false);
btnStart.Text = this.State.ToString();
}
#endregion
#region Registry
private Array EnumKeys(RegistryKey root, string subkey)
{
RegistryKey key = root.OpenSubKey(subkey);
string[] keys = key.GetSubKeyNames();
key.Close();
return keys;
}
private Array EnumValues(RegistryKey root, string subkey)
{
RegistryKey key = root.OpenSubKey(subkey);
string[] values = key.GetValueNames();
key.Close();
return values;
}
#endregion
#region Internal Event Handlers
private void Progress_Tick(int count, string prompt)
{
if (prgProgress.Maximum >= count)
{
prgProgress.Value = count;
prgProgress.Refresh();
ssStatus.Items[0].Text = prompt;
ssStatus.Refresh();
}
}
#endregion
}
}