Как проверить, является ли один путь дочерним по отношению к другому пути? - PullRequest
14 голосов
/ 11 ноября 2011

Как проверить, является ли один путь дочерним по отношению к другому пути?
Просто проверять подстроку не так, потому что могут быть такие элементы, как.и .. и т. д.

Ответы [ 7 ]

20 голосов
/ 29 апреля 2014

К сожалению, это не так просто, как StartsWith.

Вот лучший ответ, адаптированный из этого дублирующего вопроса.Я сделал это методом расширения для простоты использования.Также использование грубой силы catch, так как практически любой метод, который обращается к файловой системе, может завершиться сбоем в зависимости от прав пользователя.

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;
}
5 голосов
/ 18 октября 2016

Любое решение на основе строк потенциально может подвергаться атакам с обходом каталога или проблемам с корректностью таких вещей, как конечные косые черты. К сожалению, класс .NET Path не предоставляет эту функциональность, однако класс Uri делает в виде 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
1 голос
/ 29 марта 2019

Я использовал такой метод расширения:

    /// <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('/','\\') + "/";
    }
0 голосов
/ 04 января 2019

Я обнаружил, что это работает для Windows:

if (pathA.Equals(pathB, StringComparison.OrdinalIgnoreCase) ||
    pathA.StartsWith(pathB + "\\", StringComparison.OrdinalIgnoreCase))

Если в ваших путях могут быть завершающие символы, вы можете сначала нормализовать их следующим образом:

pathA = Path.GetFullPath(pathA);
pathB = Path.GetFullPath(pathB);
0 голосов
/ 15 апреля 2016

Была такая же проблема.Вы можете использовать StartWith(), если у вас есть путь в виде строки

if (pathA.StartsWith (pathB + "\\")) {

Хотя я не уверен, кроссплатформенный он или нет, но он работает на ПК

0 голосов
/ 11 ноября 2011

В C # вы можете сделать это так:

string cp = Path.GetFullPath(childPath);
string pp = Path.GetFullPath(parentPath);

if(pp.StartsWith(cp))
    return true;
else
    return false;
0 голосов
/ 11 ноября 2011

Это будет один из способов, у вас есть пути A и B, конвертируйте их в полные пути с помощью функции Path.GetFullPath (). Затем проверьте, является ли один из полных путей начальной подстрокой другого.

Так что это будет

if (Path.GetFullPath(A).StartsWith(Path.GetFullPath(B)) ||
    Path.GetFullPath(B).StartsWith(Path.GetFullPath(A)))
   { /* ... do your magic ... */ }
...