I have 2 strings - dir1 and dir2, and I need to check if one is sub-directory for other. I tried to go with Contains method:
dir1.contains(dir2);
Update - this I wrote originally is wrong (see below):
It seems to me that you actually stick with the basic string comparison (using .ToLower() of course) using the .StartsWith() function, along with counting the path separators, but you add in an additional consideration in regard to the number of path separators - and you need to employ something like Path.GetFullPath() on the strings beforehand to make sure you're dealing with consistent path string formats. So you'd end up with something basic and simple, like this:
string dir1a = Path.GetFullPath(dir1).ToLower();
string dir2a = Path.GetFullPath(dir2).ToLower();
if (dir1a.StartsWith(dir2a) || dir2a.StartsWith(dir1a)) {
if (dir1a.Count(x => x = Path.PathSeparator) != dir2a.Count(x => x = Path.PathSeparator)) {
// one path is inside the other path
}
}
Update...
As I discovered in using my code, the reason this is wrong, is because it does not account for cases where one directory name begins with the same characters as the entire name of the other directory. I had a case where I had one directory path of "D:\prog\dat\Mirror_SourceFiles" and another directory path of "D:\prog\dat\Mirror". Since my first path does indeed "start with" the letters "D:\prog\dat\Mirror" my code gave me a false match. I got rid of .StartsWith entirely and changed the code to this (method: split the path to the individual parts, and compare the parts up to the smaller number of parts):
// make sure "dir1" and "dir2a" are distinct from each other
// (i.e., not the same, and neither is a subdirectory of the other)
string[] arr_dir1 = Path.GetFullPath(dir1).Split(Path.DirectorySeparatorChar);
string[] arr_dir2 = Path.GetFullPath(dir2).Split(Path.DirectorySeparatorChar);
bool bSame = true;
int imax = Math.Min(arr_dir1.Length, arr_dir2.Length);
for (int i = 0; i < imax; ++i) {
if (String.Compare(arr_dir1[i], arr_dir2[i], true) != 0) {
bSame = false;
break;
}
}
if (bSame) {
// do what you want to do if one path is the same or
// a subdirectory of the other path
}
else {
// do what you want to do if the paths are distinct
}
Of course, note that in a "real program" you are going to be using the Path.GetFullPath() function in a try-catch to handle the appropriate exceptions in regard to the string you're passing into it.
In my case the path and possible subpath do not contains '..' and never end in '\':
private static bool IsSubpathOf(string path, string subpath)
{
return (subpath.Equals(path, StringComparison.OrdinalIgnoreCase) ||
subpath.StartsWith(path + @"\", StringComparison.OrdinalIgnoreCase));
}
string path1 = "C:\test";
string path2 = "C:\test\abc";
var root = Path.GetFullPath(path1);
var secondDir = Path.GetFullPath(path2 + Path.AltDirectorySeparatorChar);
if (!secondDir.StartsWith(root))
{
}
Path.GetFullPath
works great with paths, like: C:\test\..\forbidden\
DirectoryInfo di1 = new DirectoryInfo(dir1);
DirectoryInfo di2 = new DirectoryInfo(dir2);
bool isParent = di2.Parent.FullName == di1.FullName;
Or in a loop to allow for nested sub-directories, i.e. C:\foo\bar\baz is a sub directory of C:\foo :
DirectoryInfo di1 = new DirectoryInfo(dir1);
DirectoryInfo di2 = new DirectoryInfo(dir2);
bool isParent = false;
while (di2.Parent != null)
{
if (di2.Parent.FullName == di1.FullName)
{
isParent = true;
break;
}
else di2 = di2.Parent;
}
My paths could possibly contain different casing and even have untrimmed segments... This seems to work:
public static bool IsParent(string fullPath, string base)
{
var fullPathSegments = SegmentizePath(fullPath);
var baseSegments = SegmentizePath(base);
var index = 0;
while (fullPathSegments.Count>index && baseSegments.Count>index &&
fullPathSegments[index].Trim().ToLower() == baseSegments[index].Trim().ToLower())
index++;
return index==baseSegments.Count-1;
}
public static IList<string> SegmentizePath(string path)
{
var segments = new List<string>();
var remaining = new DirectoryInfo(path);
while (null != remaining)
{
segments.Add(remaining.Name);
remaining = remaining.Parent;
}
segments.Reverse();
return segments;
}
Try:
dir1.contains(dir2+"\\");