How to check if one path is a child of another path?
Just checking for substring is not a way to go, because there can items such as . and .., etc
Unfortunately it's not as simple as StartsWith
.
Here's a better answer, adapted from this duplicate question. I've made it an extension method for ease of use. Also using a brute-force catch
as just about any method that accesses the file system can fail based on user permissions.
public static bool IsSubDirectoryOf(this string candidate, string other)
{
var isChild = false;
try
{
var candidateInfo = new DirectoryInfo(candidate);
var otherInfo = new DirectoryInfo(other);
while (candidateInfo.Parent != null)
{
if (candidateInfo.Parent.FullName == otherInfo.FullName)
{
isChild = true;
break;
}
else candidateInfo = candidateInfo.Parent;
}
}
catch (Exception error)
{
var message = String.Format("Unable to check directories {0} and {1}: {2}", candidate, other, error);
Trace.WriteLine(message);
}
return isChild;
}
Any string-based solution is potentially subject to directory traversal attacks or correctness issues with things like trailing slashes. Unfortunately, the .NET Path
class does not provide this functionality, however the Uri
class does, in the form of Uri.IsBaseOf()
.
Uri potentialBase = new Uri(@"c:\dir1\");
Uri regular = new Uri(@"c:\dir1\dir2");
Uri confusing = new Uri(@"c:\temp\..\dir1\dir2");
Uri malicious = new Uri(@"c:\dir1\..\windows\system32\");
Console.WriteLine(potentialBase.IsBaseOf(regular)); // True
Console.WriteLine(potentialBase.IsBaseOf(confusing)); // True
Console.WriteLine(potentialBase.IsBaseOf(malicious)); // False
Had the same issue. You can use StartWith()
if you have the path as string
if (pathA.StartsWith (pathB + "\\")) {
Though I am not sure if it is cross platform or not, but it does work on PC
In C# you can do it like this:
string cp = Path.GetFullPath(childPath);
string pp = Path.GetFullPath(parentPath);
if(pp.StartsWith(cp))
return true;
else
return false;
I have found that this works for windows:
if (pathA.Equals(pathB, StringComparison.OrdinalIgnoreCase) ||
pathA.StartsWith(pathB + "\\", StringComparison.OrdinalIgnoreCase))
If your paths might have trailing characters, you could normalize them like this first:
pathA = Path.GetFullPath(pathA);
pathB = Path.GetFullPath(pathB);
This would be one way to go, you have path A and B, convert them to full paths with the Path.GetFullPath() function. Next check if one of the full paths is a starting substring of the other.
So that would be
if (Path.GetFullPath(A).StartsWith(Path.GetFullPath(B)) ||
Path.GetFullPath(B).StartsWith(Path.GetFullPath(A)))
{ /* ... do your magic ... */ }