user626528
user626528

Reputation: 14419

How to check if one path is a child of another path?

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

Answers (9)

GoWiser
GoWiser

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

hungdoba
hungdoba

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

Siderite Zackwehdex
Siderite Zackwehdex

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

frankl5150
frankl5150

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

Oren Melzer
Oren Melzer

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

Akhil Gupta
Akhil Gupta

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

Charlie
Charlie

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

techExplorer
techExplorer

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

Captain Coder
Captain Coder

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

Related Questions