如何从路径中提取每个文件夹的名称?

81

我的路径是\\server\folderName1\another name\something\another folder\

如果我不知道路径中有多少个文件夹,也不知道文件夹的名称,该如何将每个文件夹的名称提取到一个字符串中呢?

非常感谢。

18个回答

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

编辑: 这返回directories数组中的每个单独文件夹。你可以这样获取返回的文件夹数量:

int folderCount = directories.Length;

我添加了一个小的增强功能(在这篇文章的某个地方),但我也将其标记为正确。干得好! - granadaCoder
29
请注意,还有一个Path.AltDirectorySeparatorChar也可能需要处理(例如,通过 mypath.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar });)。 - Simon Opelt
21
这个路径 \\ticows01\c$\AgArmourFTP 上的东西已经完全毁了。抱歉,但这种方法过于简单了。 - toddmo

35

这在一般情况下是很好的:

yourPath.Split(@"\/", StringSplitOptions.RemoveEmptyEntries)
如果路径本身以斜杠(反斜杠)结尾(例如 "\ foo \ bar \"),则返回的数组中没有空元素。但是,您必须确保 yourPath 确实是一个目录而不是文件。您可以像这样找出它是什么并进行补偿,如果它是一个文件:
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
}

我相信这个答案涵盖了所有情况,而又不会太啰嗦。它将返回一个 string[] 数组,你可以使用 foreach 进行迭代,依次获取每个目录。

如果你想使用常量而不是 @"\/" 魔术字符串,你需要使用

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

然后在上面的代码中使用分隔符,而不是@"\/"。个人认为这样太冗长了,我可能不会这么做。


2
这似乎在C# 6中无法正常工作,并出现以下错误: path.Split(@"\/", StringSplitOptions.RemoveEmptyEntries); (1,12): error CS1503: Argument 1: cannot convert from 'string' to 'char' (1,19): error CS1503: Argument 2: cannot convert from 'System.StringSplitOptions' to 'char'。使用分隔符创建新的char[]可以正常工作: path.Split(new char[] { Path.DirectorySeparatorChar }, options: StringSplitOptions.RemoveEmptyEntries); 可以正常工作。 - Thoughtful Dragon

11

我看到了你的方法Wolf5370,然后向你举起了。

internal static List<DirectoryInfo> Split(this DirectoryInfo path)
{
    if(path == null) throw new ArgumentNullException("path");
    var ret = new List<DirectoryInfo>();
    if (path.Parent != null) ret.AddRange(Split(path.Parent));
    ret.Add(path);
    return ret;
}

在路径 c:\folder1\folder2\folder3 上,这将返回:

c:\

c:\folder1

c:\folder1\folder2

c:\folder1\folder2\folder3

按此顺序排列。

OR

internal static List<string> Split(this DirectoryInfo path)
{
    if(path == null) throw new ArgumentNullException("path");
    var ret = new List<string>();
    if (path.Parent != null) ret.AddRange(Split(path.Parent));
    ret.Add(path.Name);
    return ret;
}

将返回

c:\

文件夹1

文件夹2

文件夹3


这对于绝对路径非常有效,但是如果你有一个相对路径并且希望输出反映出它,那就不太适用。 - jkindwall

10

我知道这是一篇旧帖子,但我偶然发现了它 - 最终我决定采用下面的函数,因为它比上面所有的函数都更好地解决了我当时的问题:

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

1
rtn.Add(new DirectoryInfo(di)); is wrong, should be rtn.Add(di); and also change rtn.Add(new DirectoryInfo(di.Root)); for rtn.Add(di.Root); - Jaider
谢谢这个例子。如果您需要以后与文件夹交互,存储DirectoryInfo对象而不是简单字符串会很有用。 - Louis
我根据你的答案实现了一个更简洁的方法。 - K. R.

6

有几种方法可以表示文件路径。您应该使用 System.IO.Path 类来获取操作系统的分隔符,因为它在UNIX和Windows之间可能会有所不同。此外,大多数(如果我没有记错的话).NET库都接受 '\' 或 '/' 作为路径分隔符,而不管操作系统如何。出于这个原因,我建议使用 Path 类来拆分您的路径。尝试使用以下内容:

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

无论文件夹数量或名称如何,这都应该能正常工作。

5
public static IEnumerable<string> Split(this DirectoryInfo path)
{
    if (path == null) 
        throw new ArgumentNullException("path");
    if (path.Parent != null)
        foreach(var d in Split(path.Parent))
            yield return d;
    yield return path.Name;
}

1
我喜欢你的方法,但是我做了一个更简单的实现,没有递归。+1 - Roland

5

受之前答案的启发,但更简单,没有递归。此外,它不在意分隔符是什么,因为 Dir.Parent 已经涵盖了这一点:

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

要么将此代码放入一个static类中,创建一个漂亮的扩展方法; 或者省略thisstatic

作为扩展方法的使用示例,按编号访问路径部分:

    /// <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] : "";
    }

以上两种方法现在都在我的个人库中,因此有xml注释。使用示例:

    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

4
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    /// <summary>
    /// Use to emulate the C lib function _splitpath()
    /// </summary>
    /// <param name="path">The path to split</param>
    /// <param name="rootpath">optional root if a relative path</param>
    /// <returns>the folders in the path. 
    ///     Item 0 is drive letter with ':' 
    ///     If path is UNC path then item 0 is "\\"
    /// </returns>
    /// <example>
    /// string p1 = @"c:\p1\p2\p3\p4";
    /// string[] ap1 = p1.SplitPath();
    /// // ap1 = {"c:", "p1", "p2", "p3", "p4"}
    /// string p2 = @"\\server\p2\p3\p4";
    /// string[] ap2 = p2.SplitPath();
    /// // ap2 = {@"\\", "server", "p2", "p3", "p4"}
    /// string p3 = @"..\p3\p4";
    /// string root3 = @"c:\p1\p2\";
    /// string[] ap3 = p1.SplitPath(root3);
    /// // ap3 = {"c:", "p1", "p3", "p4"}
    /// </example>
    public static string[] SplitPath(this string path, string rootpath = "")
    {
        string drive;
        string[] astr;
        path = Path.GetFullPath(Path.Combine(rootpath, path));
        if (path[1] == ':')
        {
            drive = path.Substring(0, 2);
            string newpath = path.Substring(2);
            astr = newpath.Split(new[] { Path.DirectorySeparatorChar }
                , StringSplitOptions.RemoveEmptyEntries);
        }
        else
        {
            drive = @"\\";
            astr = path.Split(new[] { Path.DirectorySeparatorChar }
                , StringSplitOptions.RemoveEmptyEntries);
        }
        string[] splitPath = new string[astr.Length + 1];
        splitPath[0] = drive;
        astr.CopyTo(splitPath, 1);
        return splitPath;
    }

3
也许可以在循环中调用 Directory.GetParent?如果您想要每个目录的完整路径而不仅仅是目录名称的话。

2
快速的答案是使用.Split('\\')方法。

4
如果路径开头带有驱动器号,那么如果你想要使用Path.Combine将数组重新组合起来,请注意 - 它将会组合成类似于c:server\folderName1...这样的形式。请小心处理。 - Ben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接