I have 2 DirectoryInfo
objects and want to check if they are pointing to the same directory. Besides comparing their Fullname, are there any other better ways to do this? Please disregard the case of links.
Here's what I have.
DirectoryInfo di1 = new DirectoryInfo(@"c:\temp");
DirectoryInfo di2 = new DirectoryInfo(@"C:\TEMP");
if (di1.FullName.ToUpperInvariant() == di2.FullName.ToUpperInvariant())
{ // they are the same
...
}
Thanks.
Under Linux you could compare the INode numbers of the two files wheather they are identical. But under Windows there is no such concept, at least not that I know off. You would need to use p/invoke to resolve the links if any.
Comparing strings is the best you can do. Note that using String.Compare(str1, str2, StringComparison.InvariantCultureIgnoreCase) is a bit faster than you approach.
You can use Uri objects instead. However, your Uri objects must point to a "file" inside these directories. That file doesn't actually have to exist.
private void CompareStrings()
{
string path1 = @"c:\test\rootpath";
string path2 = @"C:\TEST\..\TEST\ROOTPATH";
string path3 = @"C:\TeSt\RoOtPaTh\";
string file1 = Path.Combine(path1, "log.txt");
string file2 = Path.Combine(path2, "log.txt");
string file3 = Path.Combine(path3, "log.txt");
Uri u1 = new Uri(file1);
Uri u2 = new Uri(file2);
Uri u3 = new Uri(file3);
Trace.WriteLine(string.Format("u1 == u2 ? {0}", u1 == u2));
Trace.WriteLine(string.Format("u2 == u3 ? {0}", u2 == u3));
}
This will print out:
u1 == u2 ? True
u2 == u3 ? True
Inspired from here:
static public bool SameDirectory(string path1, string path2)
{
return (
0 == String.Compare(
System.IO.Path.GetFullPath(path1).TrimEnd('\\'),
System.IO.Path.GetFullPath(path2).TrimEnd('\\'),
StringComparison.InvariantCultureIgnoreCase))
;
}
Works for file too...
(BTW theoretically questions are duplicate, but this is the original and the other one is the most answered one...)
HTH
Case-insensitive comparison is the best you can get. Extract it to a helper class just in case mankind comes up with a better method.
public static class DirectoryInfoExtensions
{
public static bool IsEqualTo(this DirectoryInfo left, DirectoryInfo right)
{
return left.FullName.ToUpperInvariant() == right.FullName.ToUpperInvariant();
}
}
and use:
if (di1.IsEqualTo(di2))
{
// Code here
}
Some extension methods that I wrote for a recent project includes one that will do it:
public static bool IsSame(this DirectoryInfo that, DirectoryInfo other)
{
// zip extension wouldn't work here because it truncates the longer
// enumerable, resulting in false positive
var e1 = that.EnumeratePathDirectories().GetEnumerator();
var e2 = other.EnumeratePathDirectories().GetEnumerator();
while (true)
{
var m1 = e1.MoveNext();
var m2 = e2.MoveNext();
if (m1 != m2) return false; // not same length
if (!m1) return true; // finished enumerating with no differences found
if (!e1.Current.Name.Trim().Equals(e2.Current.Name.Trim(), StringComparison.InvariantCultureIgnoreCase))
return false; // current folder in paths differ
}
}
public static IEnumerable<DirectoryInfo> EnumeratePathDirectories(this DirectoryInfo di)
{
var stack = new Stack<DirectoryInfo>();
DirectoryInfo current = di;
while (current != null)
{
stack.Push(current);
current = current.Parent;
}
return stack;
}
// irrelevant for this question, but still useful:
public static bool IsSame(this FileInfo that, FileInfo other)
{
return that.Name.Trim().Equals(other.Name.Trim(), StringComparison.InvariantCultureIgnoreCase) &&
that.Directory.IsSame(other.Directory);
}
public static IEnumerable<DirectoryInfo> EnumeratePathDirectories(this FileInfo fi)
{
return fi.Directory.EnumeratePathDirectories();
}
public static bool StartsWith(this FileInfo fi, DirectoryInfo directory)
{
return fi.Directory.StartsWith(directory);
}
public static bool StartsWith(this DirectoryInfo di, DirectoryInfo directory)
{
return di.EnumeratePathDirectories().Any(d => d.IsSame(directory));
}