如何检查一个路径是否是另一个路径的子路径

本文关键字:路径 是否是 一个 另一个 何检查 检查 | 更新日期: 2023-09-27 18:14:29

如何检查一个路径是否是另一个路径的子路径?
仅仅检查子字符串并不是一种可行的方法,因为可能存在诸如。和. .等

如何检查一个路径是否是另一个路径的子路径

不幸的是,它不像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;
}

任何基于字符串的解决方案都可能受到目录遍历攻击或诸如尾斜杠之类的正确问题的影响。不幸的是,. 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

我使用了这样的扩展方法:

    /// <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('/','''') + "/";
    }

我的解决方案是:

// 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;
}

如果childparent的子目录,则IsSubPath返回true。

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;
    }
}

在c#中你可以这样做:

string cp = Path.GetFullPath(childPath);
string pp = Path.GetFullPath(parentPath);
if(pp.StartsWith(cp))
    return true;
else
    return false;

我发现这适用于windows:

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

如果你的路径可能有尾随字符,你可以像这样首先规范化它们:

pathA = Path.GetFullPath(pathA);
pathB = Path.GetFullPath(pathB);

有同样的问题。如果路径为字符串

,则可以使用StartWith()
if (pathA.StartsWith (pathB + "''")) {

虽然我不确定它是否是跨平台的,但它确实在PC上工作

这将是一种方法,您有路径A和B,使用path . getfullpath()函数将它们转换为完整路径。接下来检查其中一个完整路径是否为另一个完整路径的起始子字符串。

也就是

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