How does one extract each folder name from a path?

Viewed 128133

My path is \\server\folderName1\another name\something\another folder\

How do I extract each folder name into a string if I don't know how many folders there are in the path and I don't know the folder names?

Many thanks

18 Answers
string mypath = @"..\folder1\folder2\folder2";
string[] directories = mypath.Split(Path.DirectorySeparatorChar);

Edit: This returns each individual folder in the directories array. You can get the number of folders returned like this:

int folderCount = directories.Length;

This is good in the general case:

yourPath.Split(@"\/", StringSplitOptions.RemoveEmptyEntries)

There is no empty element in the returned array if the path itself ends in a (back)slash (e.g. "\foo\bar\"). However, you will have to be sure that yourPath is really a directory and not a file. You can find out what it is and compensate if it is a file like this:

if(Directory.Exists(yourPath)) {
  var entries = yourPath.Split(@"\/", StringSplitOptions.RemoveEmptyEntries);
}
else if(File.Exists(yourPath)) {
  var entries = Path.GetDirectoryName(yourPath).Split(
                    @"\/", StringSplitOptions.RemoveEmptyEntries);
}
else {
  // error handling
}

I believe this covers all bases without being too pedantic. It will return a string[] that you can iterate over with foreach to get each directory in turn.

If you want to use constants instead of the @"\/" magic string, you need to use

var separators = new char[] {
  Path.DirectorySeparatorChar,  
  Path.AltDirectorySeparatorChar  
};

and then use separators instead of @"\/" in the code above. Personally, I find this too verbose and would most likely not do it.

Realise this is an old post, but I came across it looking - in the end I decided apon the below function as it sorted what I was doing at the time better than any of the above:

private static List<DirectoryInfo> SplitDirectory(DirectoryInfo parent)
{
    if (parent == null) return null;
    var rtn = new List<DirectoryInfo>();
    var di = parent;

    while (di.Name != di.Root.Name)
    {
    rtn.Add(di);
    di = di.Parent;
    }
    rtn.Add(di.Root);

    rtn.Reverse();
    return rtn;
}

There are a few ways that a file path can be represented. You should use the System.IO.Path class to get the separators for the OS, since it can vary between UNIX and Windows. Also, most (or all if I'm not mistaken) .NET libraries accept either a '\' or a '/' as a path separator, regardless of OS. For this reason, I'd use the Path class to split your paths. Try something like the following:

string originalPath = "\\server\\folderName1\\another\ name\\something\\another folder\\";
string[] filesArray = originalPath.Split(Path.AltDirectorySeparatorChar,
                              Path.DirectorySeparatorChar);

This should work regardless of the number of folders or the names.

Inspired by the earlier answers, but simpler, and without recursion. Also, it does not care what the separation symbol is, as Dir.Parent covers this:

    /// <summary>
    /// Split a directory in its components.
    /// Input e.g: a/b/c/d.
    /// Output: d, c, b, a.
    /// </summary>
    /// <param name="Dir"></param>
    /// <returns></returns>
    public static IEnumerable<string> DirectorySplit(this DirectoryInfo Dir)
    {
        while (Dir != null)
        {
            yield return Dir.Name;
            Dir = Dir.Parent;
        }
    }

Either stick this in a static class to create a nice extension method, or just leave out the this (and static).

Usage example (as an extension method) to access the path parts by number:

    /// <summary>
    /// Return one part of the directory path.
    /// Path e.g.: a/b/c/d. PartNr=0 is a, Nr 2 = c.
    /// </summary>
    /// <param name="Dir"></param>
    /// <param name="PartNr"></param>
    /// <returns></returns>
    public static string DirectoryPart(this DirectoryInfo Dir, int PartNr)
    {
        string[] Parts = Dir.DirectorySplit().ToArray();
        int L = Parts.Length;
        return PartNr >= 0 && PartNr < L ? Parts[L - 1 - PartNr] : "";
    }

Both above methods are now in my personal library, hence the xml comments. Usage example:

    DirectoryInfo DI_Data = new DirectoryInfo(@"D:\Hunter\Data\2019\w38\abc\000.d");
    label_Year.Text = DI_Data.DirectoryPart(3); // --> 2019
    label_Entry.Text = DI_Data.DirectoryPart(6);// --> 000.d

Maybe call Directory.GetParent in a loop? That's if you want the full path to each directory and not just the directory names.

The quick answer is to use the .Split('\\') method.

I use this for looping folder ftp server

public List<string> CreateMultiDirectory(string remoteFile)
      
var separators = new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };
string[] directory = Path.GetDirectoryName(remoteFile).Split(separators);

var path = new List<string>();
var folder = string.Empty;
foreach (var item in directory)
{
     folder += $@"{item}\";
     path.Add(folder);
}

return path;

Or, if you need to do something with each folder, have a look at the System.IO.DirectoryInfo class. It also has a Parent property that allows you to navigate to the parent directory.

I wrote the following method which works for me.

protected bool isDirectoryFound(string path, string pattern)
    {
        bool success = false;

        DirectoryInfo directories = new DirectoryInfo(@path);
        DirectoryInfo[] folderList = directories.GetDirectories();

        Regex rx = new Regex(pattern);

        foreach (DirectoryInfo di in folderList)
        {
            if (rx.IsMatch(di.Name))
            {
                success = true;
                break;
            }
        }

        return success;
    }

The lines most pertinent to your question being:

DirectoryInfo directories = new DirectoryInfo(@path); DirectoryInfo[] folderList = directories.GetDirectories();

I just coded this since I didn't find any already built in in C#.

/// <summary>
/// get the directory path segments.
/// </summary>
/// <param name="directoryPath">the directory path.</param>
/// <returns>a IEnumerable<string> containing the get directory path segments.</returns>
public IEnumerable<string> GetDirectoryPathSegments(string directoryPath)
{
    if (string.IsNullOrEmpty(directoryPath))
    { throw new Exception($"Invalid Directory: {directoryPath ?? "null"}"); }

    var currentNode = new System.IO.DirectoryInfo(directoryPath);

    var targetRootNode = currentNode.Root;
    if (targetRootNode == null) return new string[] { currentNode.Name };
    var directorySegments = new List<string>();
    while (string.Compare(targetRootNode.FullName, currentNode.FullName, StringComparison.InvariantCultureIgnoreCase) != 0)
    {
        directorySegments.Insert(0, currentNode.Name);
        currentNode = currentNode.Parent;
    }
    directorySegments.Insert(0, currentNode.Name);
    return directorySegments;
}

I'd like to contribute using this options (without split method)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace SampleConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var filePaths = new[]
            {
                "C:/a/b/c/d/files-samples/formdata.bmp",
                @"\\127.0.0.1\c$\a\b\c\d\formdata.bmp",
                "/usr/home/john/a/b/c/d/formdata.bmp"
            };

            foreach (var filePath in filePaths)
            {

                var directorySegments = GetDirectorySegments(filePath);
                Console.WriteLine(filePath);
                Console.WriteLine(string.Join(Environment.NewLine,
                    directorySegments.Select((e, i) => $"\t Segment#={i + 1} Text={e}")));
            }

        }

        private static IList<string> GetDirectorySegments(string filePath)
        {
            var directorySegments = new List<string>();
            if (string.IsNullOrEmpty(filePath))
                return directorySegments;

            var fileInfo = new FileInfo(filePath);
            if (fileInfo.Directory == null) 
                return directorySegments;

            for (var currentDirectory = fileInfo.Directory;
                currentDirectory != null;
                currentDirectory = currentDirectory.Parent)
                directorySegments.Insert(0, currentDirectory.Name);

            return directorySegments;
        }
    }
}

if everything goes well, an output will be like:

C:/a/b/c/d/files-samples/formdata.bmp
         Segment#=1 Text=C:\
         Segment#=2 Text=a
         Segment#=3 Text=b
         Segment#=4 Text=c
         Segment#=5 Text=d
         Segment#=6 Text=files-samples
\\127.0.0.1\c$\a\b\c\d\formdata.bmp
         Segment#=1 Text=\\127.0.0.1\c$
         Segment#=2 Text=a
         Segment#=3 Text=b
         Segment#=4 Text=c
         Segment#=5 Text=d
/usr/home/john/a/b/c/d/formdata.bmp
         Segment#=1 Text=C:\
         Segment#=2 Text=usr
         Segment#=3 Text=home
         Segment#=4 Text=john
         Segment#=5 Text=a
         Segment#=6 Text=b
         Segment#=7 Text=c
         Segment#=8 Text=d

You can still perform additional filters to GetDirectorySegments (since you have an instance of DirectoryInfo you can check atributes or use the Exist property)

Related