Svish Svish -4 years ago 139
C# Question

C#: How would you make a unique filename by adding a number?

I would like to create a method which takes either a filename as a

or a
and adds an incremented number to the filename if the file exists. But can't quite wrap my head around how to do this in a good way.

For example, if I have this FileInfo

var file = new FileInfo(@"C:\file.ext");

I would like the method to give me a new FileInfo with C:\file 1.ext if C:\file.ext
existed, and C:\file 2.ext if C:\file 1.ext existed and so on. Something like this:

public FileInfo MakeUnique(FileInfo fileInfo)
if(fileInfo == null)
throw new ArgumentNullException("fileInfo");
return fileInfo;

// Somehow construct new filename from the one we have, test it,
// then do it again if necessary.

Answer Source

Lots of good advice here. I ended up using a method written by Marc in an answer to a different question. Reformatted it a tiny bit and added another method to make it a bit easier to use "from the outside". Here is the result:

private static string numberPattern = " ({0})";

public static string NextAvailableFilename(string path)
    // Short-cut if already available
    if (!File.Exists(path))
        return path;

    // If path has extension then insert the number pattern just before the extension and return next filename
    if (Path.HasExtension(path))
        return GetNextFilename(path.Insert(path.LastIndexOf(Path.GetExtension(path)), numberPattern));

    // Otherwise just append the pattern to the path and return next filename
    return GetNextFilename(path + numberPattern);

private static string GetNextFilename(string pattern)
    string tmp = string.Format(pattern, 1);
    if (tmp == pattern)
        throw new ArgumentException("The pattern must include an index place-holder", "pattern");

    if (!File.Exists(tmp))
        return tmp; // short-circuit if no matches

    int min = 1, max = 2; // min is inclusive, max is exclusive/untested

    while (File.Exists(string.Format(pattern, max)))
        min = max;
        max *= 2;

    while (max != min + 1)
        int pivot = (max + min) / 2;
        if (File.Exists(string.Format(pattern, pivot)))
            min = pivot;
            max = pivot;

    return string.Format(pattern, max);

Only partially tested it so far, but will update if I find any bugs with it. (Marcs code works nicely!) If you find any problems with it, please comment or edit or something :)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download