Reputation: 14419
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
Upvotes: 18
Views: 13500
Reputation: 1045
IsSubPath
returns true if child
is a subdirectory of parent
.
public static bool IsSubPath(string parent, string child)
{
try
{
parent = Path.GetFullPath(parent);
if (!parent.EndsWith(Path.DirectorySeparatorChar.ToString()))
parent = parent + Path.DirectorySeparatorChar;
child = Path.GetFullPath(child);
if (child.Length <= parent.Length)
return false;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return child.StartsWith(parent, StringComparison.OrdinalIgnoreCase);
else
return child.StartsWith(parent);
}
catch
{
return false;
}
}
The function also works with non-existing paths.
Upvotes: 0
Reputation: 1
Here is my solution:
// length parentDirectory <= length subDirectory
static private bool isParentDirectory(string parentDirectory, string subDirectory)
{
if (!subDirectory.Contains(parentDirectory)) return false;
string[] folders1 = subDirectory.Split('\\');
string[] folders2 = parentDirectory.Split('\\');
for (int i = 0; i < folders2.Count(); i++)
{
if (folders2[i] != folders1[i])
return false;
}
return true;
}
Upvotes: 0
Reputation: 6570
I've used an extension method like this:
/// <summary>
/// Check if a directory is the base of another
/// </summary>
/// <param name="root">Candidate root</param>
/// <param name="child">Child folder</param>
public static bool IsBaseOf(this DirectoryInfo root, DirectoryInfo child)
{
var directoryPath = EndsWithSeparator(new Uri(child.FullName).AbsolutePath);
var rootPath = EndsWithSeparator(new Uri(root.FullName).AbsolutePath);
return directoryPath.StartsWith(rootPath, StringComparison.OrdinalIgnoreCase);
}
private static string EndsWithSeparator(string absolutePath)
{
return absolutePath?.TrimEnd('/','\\') + "/";
}
Upvotes: 2
Reputation: 31
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);
Upvotes: 0
Reputation: 760
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
Upvotes: 15
Reputation: 101
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
Upvotes: -2
Reputation: 15247
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;
}
Upvotes: 19
Reputation: 908
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;
Upvotes: 0
Reputation: 818
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 ... */ }
Upvotes: -3