How to check if directory 1 is a subdirectory of dir2 and vice versa

做~自己de王妃 提交于 2019-11-29 11:19:54

问题


What is an easy way to check if directory 1 is a subdirectory of directory 2 and vice versa?

I checked the Path and DirectoryInfo helperclasses but found no system-ready function for this. I thought it would be in there somewhere.

Do you guys have an idea where to find this?

I tried writing a check myself, but it's more complicated than I had anticipated when I started.


回答1:


You can compare directory2 to directory1's Parent property when using a DirectoryInfo in both cases.

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



回答2:


In response to the first part of the question: "Is dir1 a sub-directory of dir2?", this code should work:

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

The URIs (on Windows at least, might be different on Mono/Linux) are case-insensitive. If case sensitivity is important, use the Compare method on Uri instead.




回答3:


Here's a simpler way to do it using the Uri class:

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



回答4:


See original answer here: https://stackoverflow.com/a/31941159/134761

  • Case insensitive
  • Tolerates mix of \ and / folder delimiters
  • Tolerates ..\ in path
  • Avoids matching on partial folder names (c:\foobar not a subpath of c:\foo)

Code:

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

Test cases (NUnit):

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

Update 2015-08-18: Fix bug matching on partial folder names. Add test cases.

Update 2016-01-29: Link to original question https://stackoverflow.com/a/31941159/134761




回答5:


DirectoryInfo has a property Parent which is also a DirectoryInfo type. You can use that to to determine if your directory is a subdirectory of a parent directory.




回答6:


The second directories(d2) full name will contain the full name of the first directory(d1) if it is a sub-folder of d1.

This assumes that you are using valid directories

if (d2.FullName.Contains(d1.FullName))
{
     //dowork
}

If you need to check for mapped drives you could try

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

Code for mapped drive taken from http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/6f79f2b3-d092-431f-bc28-d15d93cf5d09




回答7:


If you have two path then look at this:

Normalize directory names in C#

http://filedirectorypath.codeplex.com/ (I don't know the quality of it)

And use this:

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

Otherwise, if you want to know whether a directory exists as a subdirectory in a path take a look on:

Directory.EnumerateDirectories

Came in .Net 4.0. Example:

Does path contain a directory starting with Console:

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



回答8:


You can use Path.GetDirectoryName Method to get parent directory. It works for directories too.




回答9:


public static bool IsSubfolder(DirectoryInfo parentPath, DirectoryInfo childPath)
{
return parentPath.FullName.StartsWith(childPath.FullName+Path.DirectorySeparatorChar);
}



回答10:


this is what I got, after first verifying that the two directory path strings are something and in a path format I know something about: shouldnotbechilddirpath.ToUpper().StartsWith(maybeparentdirpath.ToUpper())

Be sure to take out the ToUppers() if you are maybe working in a case sensitive file system.



来源:https://stackoverflow.com/questions/3525775/how-to-check-if-directory-1-is-a-subdirectory-of-dir2-and-vice-versa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!