8

Possible Duplicate:
Best way to determine if two path reference to same file in C#

So I have two Windows filenames I need to compare to determine if they are the same. One the user gave me, one given to me by another program. So how should you compare:

C:\Program Files\Application1\APP.EXE
C:\Progra~1\Applic~1\APP.EXE
C:\program files\applic~1\app.exe

I can't seem to find a way to consistently 'normalize' the path, I tried using Path.GetFullPath(path) and new FileInfo(path).FullName and neither seem to resolve this.

UPDATE:

Path.GetFullPath(path) will correct the short to long name conversion but it will not normalize case. Thus a StringComparer.OrdinalIgnoreCase.Equals(path1, path2) is required.

Community
  • 1
  • 1
csharptest.net
  • 62,602
  • 11
  • 71
  • 89

3 Answers3

4

You will need Path.GetFullPath() + case insensitive string comparison.

Running the following code:

using System;
using System.IO;

class Test {
 static void Main ()
 {
  //string [] str = new string[] {@"c:\program files\vim\vim72", @"c:\progra~1\vim\vim72"};
  string [] str = new string[] {@"c:\program files\Refere~1\microsoft", @"c:\progra~1\Refere~1\microsoft"};
  foreach (string s in str) {
   // Call s = Environment.ExpandEnvironmentVariables (s) if needed.
   Console.WriteLine (Path.GetFullPath (s));
  }
 }
}

gives:

c:\program files\Reference Assemblies\microsoft
c:\Program Files\Reference Assemblies\microsoft
Gonzalo
  • 20,805
  • 3
  • 75
  • 78
  • Delete this quick, before you get hammered on the downvote... – Philip Wallace Nov 17 '09 at 19:03
  • It works for me here. I tried c:\Progra~1\Refere~1\Microsoft and c:\Program Files\Referenced Assemblies\microsoft... – Gonzalo Nov 17 '09 at 19:05
  • Apparently he tried it. I posted the same thing and got 3 downvotes instantly. – Philip Wallace Nov 17 '09 at 19:06
  • I added my test and its output to the answer, just in case. Thanks. – Gonzalo Nov 17 '09 at 19:09
  • @xaero You posted basically "try GetFullPath" when the question says "I tried GetFullPath". Gonzalo included the necessary case-insensitive comparison, which is likely why it didn't work for the OP, and example code. – Tim Sylvester Nov 17 '09 at 19:20
  • It's worth noting that `Path.GetFullPath` does not expand variables, so e.g., comparing `%PROGRAMFILES%\Reference Assemblies\Microsoft` to `c:\program files\Reference Assemblies\Microsoft` will not work. – Tim Sylvester Nov 17 '09 at 19:21
  • Easy fix. Let me add a note to the answer... – Gonzalo Nov 17 '09 at 19:23
  • @Tim - fair enough. It's OK anyway, I got a badge for deleting my post... ;) – Philip Wallace Nov 17 '09 at 19:24
  • Also, I haven't tried it, but `GetFullPath` probably doesn't handle the junctions or links supported by recent versions of NTFS. Probably not an issue for 99.9% of people, though. – Tim Sylvester Nov 17 '09 at 19:25
  • Yes, I thought about junctions and symbolic links in unix but didn't think it was worth mentioning. – Gonzalo Nov 17 '09 at 19:25
  • I use them fairly often but that's definitely not common, you basically have to use non-MS software to do it outside the command line, e.g.: http://schinagl.priv.at/nt/hardlinkshellext/hardlinkshellext.html – Tim Sylvester Nov 17 '09 at 19:30
  • This is the monster method that GetFullPath calls: http://paste-it.net/public/haa0ee9/ – Philip Wallace Nov 17 '09 at 19:31
  • @Tim: in unix it would be readlink() and is part of the system C library. – Gonzalo Nov 17 '09 at 19:32
  • This is working for my limited case... The answers involving GetFileInformationByHandle are just too complex to deal with. Thx. – csharptest.net Nov 17 '09 at 20:01
0

a short test run says that the below code will work for the paths given:

bool CompareFileName(string file1, string file2)
        {
            var directory1 = Path.GetDirectoryName(file1);
            var directory2 = Path.GetDirectoryName(file2);
            var fileName1 = Path.GetFileName(file1);
            var fileName2 = Path.GetFileName(file2);

            return directory1.Equals(directory2, StringComparison.InvariantCultureIgnoreCase) &&
                   fileName1.Equals(fileName2, StringComparison.InvariantCultureIgnoreCase);
        }

this assumes windows platform (an assumption made due to the windows centric paths given as example paths)

Rune FS
  • 21,497
  • 7
  • 62
  • 96
0

I use the FileInfo object. If you create a fileinfo object of a file that actually exists the Directory property gives a nicely formatted path name.

You also get the additional benefit of being able to test if the file actually exists.

JayG
  • 612
  • 1
  • 6
  • 11