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

use*_*528 14 .net c# windows path

如何检查一条路径是否是另一条路径的子路径?
只检查子字符串不是一种方法,因为可以有诸如的项目.等等

Cha*_*lie 21

不幸的是,它不是那么简单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;
}
Run Code Online (Sandbox Code Playgroud)

  • 吞掉异常(不知道如何使用此方法)似乎是一种不好的做法。例如,假设该方法用于防止从包含敏感数据的某个文件夹上传信息,现在当发生异常时,数据将被上传。 (2认同)
  • 这也不适用于区分大小写的路径。`IsSubDirectoryOf(@"c:\a\b", @"c:\A")` 返回 false (2认同)
  • 这个答案没有解决为什么看似明显的解决方案“.StartsWith”不起作用,而是只是说明并解释了更复杂的解决方案(-1) (2认同)
  • 两个目录都必须存在才能使此方法起作用,这是一个严重的限制。 (2认同)

Ore*_*zer 7

任何基于字符串的解决方案都可能遭受目录遍历攻击或诸如斜杠之类的正确性问题。不幸的是,.NET Path类没有提供此功能,但是Uri该类提供了.NET 的形式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
Run Code Online (Sandbox Code Playgroud)

  • 为什么这有关系?无论如何,一个文件不能作为另一个文件的基础。为什么“ IsBaseOf”甚至会做出奇怪的猜测,例如砍掉它认为的文件名,而这显然不是调用方提出的问题?如果有这样的注意事项和怪异细节需要担心,那么您的答案至少应该解决这些问题。 (5认同)
  • IsBaseOf似乎对此不起作用。给定输入`'C:\ somerandomdir'`和`'C:\ someotherdir'`,我得到了真实的结果。 (2认同)
  • @jpmc26,那是因为你没有尾部斜杠。无法知道 'somerandomdir' 是目录名而不是文件名。如果要处理这种情况,请在调用前添加尾部斜杠。 (2认同)

Cap*_*der -3

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

那么那就是

if (Path.GetFullPath(A).StartsWith(Path.GetFullPath(B)) ||
    Path.GetFullPath(B).StartsWith(Path.GetFullPath(A)))
   { /* ... do your magic ... */ }
Run Code Online (Sandbox Code Playgroud)

  • 如果“A”是“C:\my\dir”并且“B”是“C:\my\dir2”,这是否可以正常工作?那应该是“假”,但我认为“Path.GetFullPath(B).StartsWith(Path.GetFullPath(A))”将是“真”。 (15认同)
  • 您可以将结尾斜杠附加到实际目录名称上。如果不区分大小写,则以 开头 可以使用 (2认同)
  • @jrh我相信@pinkfloydx33的建议解决了这个答案中的问题。如果答案经过编辑以包含它,那就太好了,但是 `.StartsWith` 似乎是这里发布的其他答案的一个不错的、更简单的替代方案。更重要的是,其他答案没有提供“.StartsWith”不起作用的任何坚实理由。@Charlie 得票第二高的答案并没有解决为什么 `.StartsWith` 不起作用,它只是声明了它。 (2认同)