65.9K
CodeProject is changing. Read more.
Home

Finding a free file name and number combination

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (4 votes)

Jun 29, 2013

CPOL
viewsIcon

12866

One of the tasks we often have to do is rename a file before creating a new version. But when we want to keep multiple versions, how do we find out which ones already exist?

Introduction

One of the tasks we often have to do is rename a file before creating a new version. The obvious way to do this is to rename the existing file so it has a number suffix:

MyFile.log
MyFile1.log
MyFile2.log
...

But when we want to keep multiple versions, how do we find out which ones already exist? 

Background

This started with a QA question and I thought it worth converting my answer to a method and submitting it for posterity! :laugh:

The Copy'n'Paste bit 

/// <summary>
/// Find the number at the end of the string
/// </summary>
private Regex fileNumber = new Regex("\\d+$", RegexOptions.Compiled);
/// <summary>
/// Get the next free file number given a base file name
/// </summary>
/// <param name="path">Path to base file</param>
/// <returns>Path to free file name</returns>
private string GetFreeFileNumber(string path)
    {
    string pathOnly = path.Substring(0, path.LastIndexOf('\\') + 1);
    string nameOnly = Path.GetFileNameWithoutExtension(path);
    string extOnly = Path.GetExtension(path);
    string[] files = Directory.GetFiles(pathOnly, nameOnly + "*" + extOnly);
    int largest = files.Max(f => GetFileNumber(f));
    return string.Format("{0}{1}{2}{3}", pathOnly, nameOnly, largest + 1, extOnly);
    }
/// <summary>
/// Get the number (if any) at the end of a filename
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
private int GetFileNumber(string file)
    {
    Match m = fileNumber.Match(Path.GetFileNameWithoutExtension(file));
    if (!m.Success) return 0;
    return int.Parse(m.Value);
    }

How it works  

First, break the base file path into its important parts: The folder it is in, the file name, and the extension.

Then read all the files in that folder with the same extension, that start with the file name.

Then use a Regex to extract the number from each filename, and use Linq extension methods to find the largest. We can then return a filename which includes a number one larger. 

File.Move[^] can then rename the existing file.  

Using the code  

Easy: Call the GetFreeFileNumber method, passing the existing base file path:

MessageBox.Show(GetFreeFileNumber(@"D:\Temp\MyLogFile.log"));

History

2013 Jun 30 Addition of "+ 1" to the pathOnly substring - otherwise it returns a filename with a "\" missing... :O