C# 如何检查目录1是否是dir2的子目录,反之亦然

C# 如何检查目录1是否是dir2的子目录,反之亦然,c#,directory,directory-structure,C#,Directory,Directory Structure,检查目录1是否为目录2的子目录以及目录1是否为目录2的子目录的简单方法是什么 我检查了Path和DirectoryInfo helperclass,但没有找到用于此的系统就绪函数。我以为它会在那里的某个地方 你们知道在哪里可以找到这个吗 我试着自己写一张支票,但它比我开始时预想的要复杂得多。如果你有两条路,那么看看这个: (我不知道它的质量) 并使用以下命令: var ancestor = new DirectoryPathAbsolute(ancestorPath); var child =

检查目录1是否为目录2的子目录以及目录1是否为目录2的子目录的简单方法是什么

我检查了Path和DirectoryInfo helperclass,但没有找到用于此的系统就绪函数。我以为它会在那里的某个地方

你们知道在哪里可以找到这个吗


我试着自己写一张支票,但它比我开始时预想的要复杂得多。

如果你有两条路,那么看看这个:

(我不知道它的质量)

并使用以下命令:

var ancestor = new DirectoryPathAbsolute(ancestorPath);
var child = new DirectoryPathAbsolute(childPath);

var res = child.IsChildDirectoryOf(ancestor); //I don't think it actually checks for case-sensitive filesystems
否则,如果您想知道某个目录是否作为路径中的子目录存在,请查看:

Directory.EnumerateDirectories
进入
.NET4.0
。例如:

path
是否包含以
Console
开头的目录:

//* is a wildcard. If you remove it, it search for directories called "Console"
var res = Directory.EnumerateDirectories(@path, "Console*", SearchOption.AllDirectories).Any();

您可以使用获取父目录。它也适用于目录。

在这两种情况下使用DirectoryInfo时,您可以比较directory2和directory1

DirectoryInfo d1 = new DirectoryInfo(@"C:\Program Files\MyApp");
DirectoryInfo d2 = new DirectoryInfo(@"C:\Program Files\MyApp\Images");

if(d2.Parent.FullName == d1.FullName)
{
    Console.WriteLine ("Sub directory");
}

DirectoryInfo有一个属性父级,也是DirectoryInfo类型。您可以使用它来确定您的目录是否是父目录的子目录。

如果是d1的子文件夹,则第二个目录(d2)的全名将包含第一个目录(d1)的全名

这假定您使用的是有效的目录

如果需要检查映射驱动器,可以尝试

    static void Main(string[] args)
    {
        if (GetUNCPath(d2.FullName).ToLower().Contains(GetUNCPath(d1.FullName).ToLower()))
        {
        }
    }

    [DllImport("mpr.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern int WNetGetConnection(
        [MarshalAs(UnmanagedType.LPTStr)] string localName,
        [MarshalAs(UnmanagedType.LPTStr)] StringBuilder remoteName, ref int length);

    private static string GetUNCPath(string originalPath)
    {

        StringBuilder sb = new StringBuilder(512);
        int size = sb.Capacity;
        // look for the {LETTER}: combination ...
        if (originalPath.Length > 2 && originalPath[1] == ':')
        {
            // don't use char.IsLetter here - as that can be misleading
            // the only valid drive letters are a-z && A-Z.
            char c = originalPath[0];
            if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
            {
                int error = WNetGetConnection(originalPath.Substring(0, 2), sb, ref size);
                if (error == 0)
                {
                    DirectoryInfo dir = new DirectoryInfo(originalPath);
                    string path = Path.GetFullPath(originalPath).Substring(Path.GetPathRoot(originalPath).Length);
                    return Path.Combine(sb.ToString().TrimEnd(), path);
                }
            }
        }
        return originalPath;
    }
static void Main(字符串[]args)
{
if(GetUNCPath(d2.FullName).ToLower()包含(GetUNCPath(d1.FullName.ToLower()))
{
}
}
[DllImport(“mpr.dll”,CharSet=CharSet.Unicode,SetLastError=true)]
私有静态外部int WNetGetConnection(
[Marshallas(UnmanagedType.LPTStr)]字符串localName,
[Marshallas(UnmanagedType.LPTStr)]StringBuilder remoteName,ref int length);
私有静态字符串GetUNCPath(字符串原始路径)
{
StringBuilder sb=新的StringBuilder(512);
int size=sb.容量;
//寻找{字母}:组合。。。
如果(originalPath.Length>2&&originalPath[1]==':')
{
//不要在这里使用char.isleter,因为这可能会产生误导
//唯一有效的驱动器号是a-z&&a-z。
char c=原始路径[0];

如果((c>='a'&&c='a'&&c回答问题的第一部分:“dir1是dir2的子目录吗?”,则此代码应适用于:

public bool IsSubfolder(string parentPath, string childPath)
{
    var parentUri = new Uri(parentPath);
    var childUri = new DirectoryInfo(childPath).Parent;
    while (childUri != null)
    {
        if(new Uri(childUri.FullName) == parentUri)
        {
            return true;
        }
        childUri = childUri.Parent;
    }
    return false;
}

URI
s(至少在Windows上,在Mono/Linux上可能不同)不区分大小写。如果区分大小写很重要,请改用
Uri
上的
Compare
方法。

这是我得到的,在首先验证两个目录路径字符串是什么并且是我知道的路径格式后:
不应该是childdirpath.ToUpper().StartsWith(可能是parentdirpath.ToUpper())


如果您在区分大小写的文件系统中工作,请务必取出ToUppers()。

使用Uri类有一种更简单的方法:

var parentUri = new Uri(parentPath);
var childUri = new Uri(childPath);
if (parentUri != childUri && parentUri.IsBaseOf(childUri))
{
   //dowork
}

请参见此处的原始答案:

  • 不区分大小写
  • 允许混合使用
    \
    /
    文件夹分隔符
  • 允许路径中的
    。\
  • 避免匹配部分文件夹名称(
    c:\foobar
    不是
    c:\foo
    的子路径)
代码:

public static class StringExtensions
{
    /// <summary>
    /// Returns true if <paramref name="path"/> starts with the path <paramref name="baseDirPath"/>.
    /// The comparison is case-insensitive, handles / and \ slashes as folder separators and
    /// only matches if the base dir folder name is matched exactly ("c:\foobar\file.txt" is not a sub path of "c:\foo").
    /// </summary>
    public static bool IsSubPathOf(this string path, string baseDirPath)
    {
        string normalizedPath = Path.GetFullPath(path.Replace('/', '\\')
            .WithEnding("\\"));

        string normalizedBaseDirPath = Path.GetFullPath(baseDirPath.Replace('/', '\\')
            .WithEnding("\\"));

        return normalizedPath.StartsWith(normalizedBaseDirPath, StringComparison.OrdinalIgnoreCase);
    }

    /// <summary>
    /// Returns <paramref name="str"/> with the minimal concatenation of <paramref name="ending"/> (starting from end) that
    /// results in satisfying .EndsWith(ending).
    /// </summary>
    /// <example>"hel".WithEnding("llo") returns "hello", which is the result of "hel" + "lo".</example>
    public static string WithEnding([CanBeNull] this string str, string ending)
    {
        if (str == null)
            return ending;

        string result = str;

        // Right() is 1-indexed, so include these cases
        // * Append no characters
        // * Append up to N characters, where N is ending length
        for (int i = 0; i <= ending.Length; i++)
        {
            string tmp = result + ending.Right(i);
            if (tmp.EndsWith(ending))
                return tmp;
        }

        return result;
    }

    /// <summary>Gets the rightmost <paramref name="length" /> characters from a string.</summary>
    /// <param name="value">The string to retrieve the substring from.</param>
    /// <param name="length">The number of characters to retrieve.</param>
    /// <returns>The substring.</returns>
    public static string Right([NotNull] this string value, int length)
    {
        if (value == null)
        {
            throw new ArgumentNullException("value");
        }
        if (length < 0)
        {
            throw new ArgumentOutOfRangeException("length", length, "Length is less than zero");
        }

        return (length < value.Length) ? value.Substring(value.Length - length) : value;
    }
}
更新2015-08-18:修复部分文件夹名称上的错误匹配。添加测试用例


更新2016-01-29:链接到原始问题

在中编写的优秀测试用例的帮助下,我在.NET Core 3.1 for Windows上编写了以下更简单的扩展方法:

public static bool IsSubPathOf(this string dirPath, string baseDirPath, StringComparison comparisonType = StringComparison.OrdinalIgnoreCase)
{
    dirPath = dirPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
    if (!dirPath.EndsWith(Path.DirectorySeparatorChar))
    {
      dirPath += Path.DirectorySeparatorChar;
    }
  
    baseDirPath = baseDirPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
    if (!baseDirPath.EndsWith(Path.DirectorySeparatorChar))
    {
      baseDirPath += Path.DirectorySeparatorChar;
    }

    string dirPathUri = new Uri(dirPath).LocalPath;
    string baseDirUri = new Uri(baseDirPath).LocalPath;

    return dirPathUri.Contains(baseDirUri, comparisonType);
}

这对于简单的情况很有效,但是\\server\m和i:\m\f呢?我可能映射到服务器,但也可能不映射到服务器。Windows上的ex
“C:\users\user”
“C:\users”
又如何呢抱歉,-1因为
包含的内容产生误报,这将不起作用。请尝试
@“C:\users\lasse”
@“C:\users\”
如何操作?
ToLower
可以在Windows上工作,但如何处理区分大小写的系统以及像“C:/users”“C:\users”这样的内容类似于d2.Parent.FullName.Equals(d1.FullName,StringComparison.InvariantCultureIgnoreCase)的代码
,也许?同样,在可能不正确的区分大小写的文件系统上。很抱歉,-1,因为它不起作用,不仅是在大小写上,而且是在路径是否包含尾部反斜杠上。如果路径被指定为C:\dir1(它会导致路径C:\),则这不起作用如果路径被指定为c:\dir1\n,则它确实有效。如果UNC路径
IsSubfolder(@“\\shared”,@“\\shared\a”)
,则它不起作用。Uri.IsBaseOf很好,但对于所问问题,它有问题:1)如果路径相同,则返回true 2)如果childPath是sub-sub-dir,等等,则返回true-本质上是递归子目录;而问题似乎是要立即检查子目录。3)路径需要以斜杠结尾,否则Uri会将它们视为文件路径。只需指出这一点,因为问题中的路径是@“C:\Program Files\MyApp”和@“C:\Program Files\MyApp\Images”,因此应添加斜杠以便正确使用,即@“C:\Program Files\MyApp\”和@“C:\Program Files\MyApp\Images”\“。但是,尽管如此,Uri.IsBaseOf似乎在递归检查一个目录是否位于另一个目录下方面做得很好。为了避免在两个目录相同的情况下返回true,它们似乎比较好,所以只需更改为:if(parentUri!=childUri&&parentUri.IsBaseOf(childUri))是的,这完全有道理,只是编辑了答案以检查是否相同。谢谢!请注意,URI类的问题可能会阻止在非windows计算机上使用.Net Core。要解决此问题,您可以在路径前添加字符串“file://”。这与问题相同,您将得到错误的po
[TestFixture]
public class StringExtensionsTest
{
    [TestCase(@"c:\foo", @"c:", Result = true)]
    [TestCase(@"c:\foo", @"c:\", Result = true)]
    [TestCase(@"c:\foo", @"c:\foo", Result = true)]
    [TestCase(@"c:\foo", @"c:\foo\", Result = true)]
    [TestCase(@"c:\foo\", @"c:\foo", Result = true)]
    [TestCase(@"c:\foo\bar\", @"c:\foo\", Result = true)]
    [TestCase(@"c:\foo\bar", @"c:\foo\", Result = true)]
    [TestCase(@"c:\foo\a.txt", @"c:\foo", Result = true)]
    [TestCase(@"c:\FOO\a.txt", @"c:\foo", Result = true)]
    [TestCase(@"c:/foo/a.txt", @"c:\foo", Result = true)]
    [TestCase(@"c:\foobar", @"c:\foo", Result = false)]
    [TestCase(@"c:\foobar\a.txt", @"c:\foo", Result = false)]
    [TestCase(@"c:\foobar\a.txt", @"c:\foo\", Result = false)]
    [TestCase(@"c:\foo\a.txt", @"c:\foobar", Result = false)]
    [TestCase(@"c:\foo\a.txt", @"c:\foobar\", Result = false)]
    [TestCase(@"c:\foo\..\bar\baz", @"c:\foo", Result = false)]
    [TestCase(@"c:\foo\..\bar\baz", @"c:\bar", Result = true)]
    [TestCase(@"c:\foo\..\bar\baz", @"c:\barr", Result = false)]
    public bool IsSubPathOfTest(string path, string baseDirPath)
    {
        return path.IsSubPathOf(baseDirPath);
    }
}
public static bool IsSubfolder(DirectoryInfo parentPath, DirectoryInfo childPath)
{
return parentPath.FullName.StartsWith(childPath.FullName+Path.DirectorySeparatorChar);
}
public static bool IsSubPathOf(this string dirPath, string baseDirPath, StringComparison comparisonType = StringComparison.OrdinalIgnoreCase)
{
    dirPath = dirPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
    if (!dirPath.EndsWith(Path.DirectorySeparatorChar))
    {
      dirPath += Path.DirectorySeparatorChar;
    }
  
    baseDirPath = baseDirPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
    if (!baseDirPath.EndsWith(Path.DirectorySeparatorChar))
    {
      baseDirPath += Path.DirectorySeparatorChar;
    }

    string dirPathUri = new Uri(dirPath).LocalPath;
    string baseDirUri = new Uri(baseDirPath).LocalPath;

    return dirPathUri.Contains(baseDirUri, comparisonType);
}