-2

I want to check if two strings are paths to the same file or folder.

I've seen two questions dealing with this: C# Canonical file names and How can one get an absolute or normalized file path in .NET? .

All answers on both are wrong.

On Windows C:\A.TXT is the same file as c:\a.txt. AFAIK on UNIX/LINUX it's not, and on MacOS it depends on the user. (The code might be used on .Net MAUI on different OSs.) And it might depend on the file system even within one OS. Non of the answers there address that. But over a decade has passed since those questions were asked, and that's a lot in computer-years.

So, does .Net (perhaps .Net 7.0) have something for this?

More info: I don't want to touch the file system such as by opening both files and checking whether both point to the same one. I just want to do a text comparison. And I don't care about "different" files pointing to the same file such as by symbolic links etc. so it's fine if the files are considered different by whatever the answer is, even though they point to the same actual file.

EDIT

Some of the paths will be stored, and I need to know that they point to the same file if the user changed from uppercase to lowercase (on Windows). I also need a durable way to check file systems and OSs. Something that will be updated if filesystems will change etc. Like for example NTFS case-sensitive NTFS folders which most commentators here seem not to know about. There might be other pitfalls as well.

Either a Canonical(path) or a AreSame(path1, path2) would be welcome.

ispiro
  • 26,556
  • 38
  • 136
  • 291
  • So in essence, you want on Windows to compare two file paths, ignoring case. And on Linux you want to compare two file paths, not ignoring case. And on Mac, you want to compare them, and sometimes ignore the case and sometimes not depending on the user. What's to stop you from writing the code to do that? – mason Dec 28 '22 at 20:53
  • You have to touch the file system to get the actual case of the file name. You don't have to open the file, but you at least have to look at the directory entry. – madreflection Dec 28 '22 at 20:55
  • MacOS' file system (APFS) is case-**in**sensitive/case-preserving by default. While the disk(s) could be formatted to use the case-sensitive flavor of APFS, the system owner would need to go out of their way to do that. As far as a "canonical" file path, there is no such thing. `/foo/bar/bazbat.txt`, `/FOO/bar/BAZBAT.txt`, and `/FOO/BAR/BAZBAT.txt`, but none of them are any more "canonical" than the other: they're just text. – Nicholas Carey Dec 28 '22 at 20:55
  • @mason My preference for writing code that won't break easily. – ispiro Dec 28 '22 at 20:57
  • @madreflection Thanks. I don't mind touching it once to get that. What I care about is that if I need to compare a million pairs of paths, I won't need to touch it a million (or two) times. – ispiro Dec 28 '22 at 20:58
  • 2
    Operating systems can mount file systems that behave differently than their default filesystems. So looking at the operating system alone will not suffice. One would have to look at the storage location. – NineBerry Dec 28 '22 at 20:59
  • 1
    Can you say a bit more about the background of the question? – NineBerry Dec 28 '22 at 21:00
  • @NineBerry Agreed. That is one of the reasons I don't want to simply test for the OS. – ispiro Dec 28 '22 at 21:00
  • To look at the directory entry, you can use `Directory.GetFiles` and provide the exact path and file name. It will return one entry (if the file exists) with the correct case. But if you're doing this for a million files, you'd be better off using `Directory.GetFiles` once (no filespec) and doing a case-insensitive test for each file name against that list. – madreflection Dec 28 '22 at 21:02
  • @madreflection That would touch the file system a lot. But besides that, some of the paths are stored, and if the name changed from uppercase to lowercase, I need to recognize it's the same file (on Windows). – ispiro Dec 28 '22 at 21:04
  • @NineBerry Some filenames will have been stored, and now compared to existing files. If the name has changed from uppercase to lowercase, I want to know it's the same file (on Windows). – ispiro Dec 28 '22 at 21:04
  • If you do it for each file, yes, but as I said, if you're doing that for a million files, get the directory listing in one shot so you don't have to make individual queries to the file system. But you have to ask the file system for the canonical case of the file. – madreflection Dec 28 '22 at 21:05
  • @madreflection `But you have to ask the file system for the canonical case of the file.` - That is ***exactly*** what I'm asking. How is that done (on .Net). – ispiro Dec 28 '22 at 21:09
  • So see my earlier comment. `Directory.GetFiles(exactDirectory, exactFileName).SingleOrDefault()`. That will do it for one file. If you have many files to check in that directory, get the full listing (no second parameter) and the results will have the canonical names for all of them. It's one hit to the file system, and yes, it could be a long list, but you lose the overhead of making a call for each individual file. – madreflection Dec 28 '22 at 21:12
  • @madreflection Did you see what I wrote that paths will be stored, and there case might be changed (by the user)? Also, see my edit for more information about pitfalls, in the question. – ispiro Dec 28 '22 at 21:14
  • You'll have to do it recursively up the tree. Your requirement involves complexity. – madreflection Dec 28 '22 at 21:15
  • NTFS does not have "canonical case for file" (obviously, since it is case-preserving, and when not viewed via Win32 API is case-sensitive)... So it is quite unclear what you are looking for on Windows (as FAT16/FAT32 is quite rare this days) – Alexei Levenkov Dec 28 '22 at 21:15
  • @AlexeiLevenkov I want code that will run **dependably** on Windows, MacOS, iOS,... and on any file system they're using, and with some folders being case sensitive while others are not. Some .Net method `Canonical(path)` or `AreSame(path1, path2)`. (Multiple OSs - through .Net MAUI) – ispiro Dec 28 '22 at 21:20
  • 1
    Then I think the answer for you is clear: you have very specific needs, and you'll need to implement something yourself that handles your needs. If you want it to be dependable, then implement tests and verify that the behavior works as you expected. There's nothing implemented that will do exactly what you want in the way you want to do it. – mason Dec 29 '22 at 14:30

1 Answers1

-2

Filenames are just text. Both Windows and MacOS are by default, case-insensitive but case-preserving file systems. MacOS allows one to format a drive with a case-sensitive filesystem; I can't remember whether or not NTFS has such an option.

In either event, to compare to strings in a case-insenstive manner, use string.Equals():

string fn1 = GetFirstFileName();
string fn2 = GetSecondFileName();
bool   areSame = fn1.Equals(fn2, StringComparision.OrdinalIgnoreCase );

To put them in a collection, list a Dictionary<TKey,TValue> or a set, use the appropriate constructor and pass it the StringComparer.OrdinalIgnoreCase as its key comparer.

Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135
  • 1
    https://stackoverflow.com/questions/33998669/windows-ntfs-and-case-sensitivity (since you said you can't remember that) – Alexei Levenkov Dec 28 '22 at 21:06
  • This is already mentioned in the answers to the questions I linked to. This doesn't help since I need a good way to check file systems and OSs. Something that will be updated if filesystems will change etc. – ispiro Dec 28 '22 at 21:06