views:

92

answers:

5

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.

A: 

If you have two path then look at this:

http://stackoverflow.com/questions/1214513/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();
lasseespeholt
+1  A: 

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

Giorgi
+2  A: 

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");
}
fletcher
This will not work. Try `@"C:\users\lasse"` and `@"c:\USERS\"`
lasseespeholt
How would you do it? `ToLower` would work on Windows but what to do with case-sensitive systems and where something is written like "C:/users" <> "c:\users"
lasseespeholt
Something along the lines of `d2.Parent.FullName.Equals(d1.FullName, StringComparison.InvariantCultureIgnoreCase)`, perhaps?
fletcher
Again, on a case-sensitive filesystem that may not be correct.
lasseespeholt
A: 

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.

Thiago Santos
+2  A: 

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

Quinn351
this works well for simple cases but what about \\server\m and i:\m\f where i might be mapped to server but it might also not be
Rune FS
and what about ex `"C:\users\user"` and `"c:\USERS"` on Windows. `ToLower` will not work on Unix
lasseespeholt
.contains will return a false positive for "c:\dir" and "c:\dir1"
sjors miltenburg