C# Filepath Recasing

Jeremy Edwards picture Jeremy Edwards · Jan 26, 2009 · Viewed 9.4k times · Source

I'm trying to write a static member function in C# or find one in the .NET Framework that will re-case a file path to what the filesystem specifies.

Example:

string filepath = @"C:\temp.txt";
filepath = FileUtility.RecaseFilepath(filepath);

// filepath = C:\Temp.TXT
// Where the real fully qualified filepath in the NTFS volume is C:\Temp.TXT

I've tried the following code below and many variants of it and it still doesn't work. I know Windows is case-insensitive in general but I need to pass these file paths to ClearCase which considers file path casing since it's a Unix and Windows application.

public static string GetProperFilePathCapitalization(string filepath)
{
    string result = "";

    try
    {
        result = Path.GetFullPath(filepath);
        DirectoryInfo dir = new DirectoryInfo(Path.GetDirectoryName(result));
        FileInfo[] fi = dir.GetFiles(Path.GetFileName(result));
        if (fi.Length > 0)
        {
            result = fi[0].FullName;
        }
    }
    catch (Exception)
    {
        result = filepath;
    }

    return result;
}

Answer

Ants picture Ants · Jan 26, 2009

This is a pretty simple implementation that assumes that the file and directories all exist and are accessible:

static string GetProperDirectoryCapitalization(DirectoryInfo dirInfo)
{
    DirectoryInfo parentDirInfo = dirInfo.Parent;
    if (null == parentDirInfo)
        return dirInfo.Name;
    return Path.Combine(GetProperDirectoryCapitalization(parentDirInfo),
                        parentDirInfo.GetDirectories(dirInfo.Name)[0].Name);
}

static string GetProperFilePathCapitalization(string filename)
{
    FileInfo fileInfo = new FileInfo(filename);
    DirectoryInfo dirInfo = fileInfo.Directory;
    return Path.Combine(GetProperDirectoryCapitalization(dirInfo),
                        dirInfo.GetFiles(fileInfo.Name)[0].Name);
}

There is a bug with this, though: Relative paths are converted to absolute paths. Your original code above did the same, so I'm assuming that you do want this behavior.