【问题标题】:How does one extract each folder name from a path?如何从路径中提取每个文件夹名称?
【发布时间】:2008-12-30 19:55:53
【问题描述】:

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

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

非常感谢

【问题讨论】:

    标签: c# string


    【解决方案1】:
    string mypath = @"..\folder1\folder2\folder2";
    string[] directories = mypath.Split(Path.DirectorySeparatorChar);
    

    编辑: 这将返回目录数组中的每个单独的文件夹。您可以像这样获取返回的文件夹数:

    int folderCount = directories.Length;
    

    【讨论】:

    • 我添加了一个小改进(在这篇文章的某处),但我也将其标记为正确。打得好!
    • 请注意,有一个Path.AltDirectorySeparatorChar 可能也需要处理。 (例如通过mypath.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar });
    • 这在\\ticows01\c$\AgArmourFTP 这样的路径上完全被破坏了。抱歉,方法太简单了。
    【解决方案2】:

    这在一般情况下很好:

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

    然后在上面的代码中使用separators 而不是@"\/"。就个人而言,我觉得这太冗长了,很可能不会这样做。

    【讨论】:

    • 这在 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); 确实有效。
    【解决方案3】:

    意识到这是一篇旧帖子,但我发现它是在寻找 - 最后我决定使用下面的函数,因为它比上述任何一个都更好地对我当时正在做的事情进行排序:

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

    【讨论】:

    • rtn.Add(new DirectoryInfo(di)); 是错误的,应该是rtn.Add(di); 并且还将rtn.Add(new DirectoryInfo(di.Root)); 更改为rtn.Add(di.Root);
    • 感谢这个例子。如果您以后需要与文件夹交互,则存储 DirectoryInfo 对象而不是简单的字符串很有用。
    • 受您的回答启发,我在下面实现了一个更简洁的方法。
    【解决方案4】:

    我看到你的 method 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

    按顺序

    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:\

    folder1

    folder2

    folder3

    【讨论】:

      【解决方案5】:

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

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

      无论文件夹数量或名称如何,这都应该有效。

      【讨论】:

        【解决方案6】:
        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
        【解决方案7】:
            // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            /// <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;
            }
        

        【讨论】:

          【解决方案8】:

          受早期答案的启发,但更简单,并且没有递归。此外,它并不关心分隔符号是什么,因为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 类中以创建一个不错的扩展方法,要么直接省略 this(和 static)。

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

              /// <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 cmets。使用示例:

              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
          

          【讨论】:

            【解决方案9】:

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

            【讨论】:

            • 如果您想将阵列与Path.Combine 重新组合在一起,如果路径的开头有驱动器号,请注意 - 这将组合为c:server\folderName1...
            【解决方案10】:

            也许循环调用Directory.GetParent?那就是如果您想要每个目录的完整路径而不仅仅是目录名称。

            【讨论】:

              【解决方案11】:

              我用它来循环文件夹 ftp 服务器

              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;
              

              【讨论】:

                【解决方案12】:

                或者,如果您需要对每个文件夹执行一些操作,请查看 System.IO.DirectoryInfo 类。它还有一个 Parent 属性,允许您导航到父目录。

                【讨论】:

                  【解决方案13】:

                  我编写了以下对我有用的方法。

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

                  与您的问题最相关的几行是:

                  DirectoryInfo 目录 = new DirectoryInfo(@path); DirectoryInfo[] 文件夹列表 = 目录.GetDirectories();

                  【讨论】:

                    【解决方案14】:
                    DirectoryInfo objDir = new DirectoryInfo(direcotryPath);
                    DirectoryInfo [] directoryNames =  objDir.GetDirectories("*.*", SearchOption.AllDirectories);
                    

                    这将为您提供所有目录和子目录。

                    【讨论】:

                    • 如果它们存在,那就是。
                    【解决方案15】:

                    我正在补充马特布鲁内尔的答案。

                                string[] directories = myStringWithLotsOfFolders.Split(Path.DirectorySeparatorChar);
                    
                                string previousEntry = string.Empty;
                                if (null != directories)
                                {
                                    foreach (string direc in directories)
                                    {
                                        string newEntry = previousEntry + Path.DirectorySeparatorChar + direc;
                                        if (!string.IsNullOrEmpty(newEntry))
                                        {
                                            if (!newEntry.Equals(Convert.ToString(Path.DirectorySeparatorChar), StringComparison.OrdinalIgnoreCase))
                                            {
                                                Console.WriteLine(newEntry);
                                                previousEntry = newEntry;
                                            }
                                        }
                                    }
                                }
                    

                    这应该给你:

                    “\服务器”

                    "\server\folderName1"

                    "\server\folderName1\另一个名称"

                    "\server\folderName1\另一个名称\某事"

                    "\server\folderName1\另一个名称\something\另一个文件夹\"

                    (或按每个值的字符串长度对生成的集合进行排序。

                    【讨论】:

                      【解决方案16】:

                      这是对 Wolf 答案的修改,它省略了根并修复了似乎是几个错误的问题。我用它来生成面包屑,我不想显示根目录。

                      这是DirectoryInfo 类型的扩展。

                      public static List<DirectoryInfo> PathParts(this DirectoryInfo source, string rootPath)
                      {
                        if (source == null) return null;
                        DirectoryInfo root = new DirectoryInfo(rootPath);
                        var pathParts = new List<DirectoryInfo>();
                        var di = source;
                      
                        while (di != null && di.FullName != root.FullName)
                        {
                          pathParts.Add(di);
                          di = di.Parent;
                        }
                      
                        pathParts.Reverse();
                        return pathParts;
                      }
                      

                      【讨论】:

                        【解决方案17】:

                        我只是编写了这个代码,因为我没有找到任何已经内置在 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;
                        }
                        

                        【讨论】:

                          【解决方案18】:

                          我想使用此选项(不使用拆分方法)进行贡献

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

                          如果一切顺利,输出会是这样的:

                          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
                          

                          您仍然可以对 GetDirectorySegments 执行其他过滤器(因为您有一个 DirectoryInfo 实例,您可以检查属性或使用 Exist 属性)

                          【讨论】:

                            猜你喜欢
                            • 2013-07-13
                            • 1970-01-01
                            • 1970-01-01
                            • 2023-03-12
                            • 2011-01-25
                            • 1970-01-01
                            • 2016-12-29
                            • 2018-04-21
                            相关资源
                            最近更新 更多