




Быстрый ответ - использовать метод .Split ('\\').
Может быть, вызвать Directory.GetParent в цикле? Это если вам нужен полный путь к каждому каталогу, а не только имена каталогов.
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. Извините, но подход слишком упрощен.
Или, если вам нужно что-то сделать с каждой папкой, взгляните на класс System.IO.DirectoryInfo. У него также есть свойство Parent, которое позволяет переходить к родительскому каталогу.
Путь к файлу можно представить несколькими способами. Вы должны использовать класс System.IO.Path для получения разделителей для ОС, поскольку он может различаться в UNIX и Windows. Кроме того, большинство (или все, если я не ошибаюсь) .NET-библиотек принимают в качестве разделителя пути либо '\', либо '/', независимо от ОС. По этой причине я бы использовал класс Path для разделения ваших путей. Попробуйте что-нибудь вроде следующего:
string originalPath = "\\server\\folderName1\\another\ name\\something\\another folder\\";
string[] filesArray = originalPath.Split(Path.AltDirectorySeparatorChar,
Path.DirectorySeparatorChar);
Это должно работать независимо от количества папок или имен.
Это хорошо в общем случае:
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); действительно работает.
Я написал следующий метод, который мне подходит.
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 каталогов = новый DirectoryInfo (@path); DirectoryInfo [] folderList = каталоги.GetDirectories ();
DirectoryInfo objDir = new DirectoryInfo(direcotryPath);
DirectoryInfo [] directoryNames = objDir.GetDirectories("*.*", SearchOption.AllDirectories);
Это даст вам все каталоги и подкаталоги.
Если они существуют, то есть.
Я добавляю ответ Мэтта Брунелла.
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;
}
}
}
}
Это должно дать вам:
"\ сервер"
"\ сервер \ имя_папки1"
"\ server \ folderName1 \ другое имя"
"\ server \ folderName1 \ другое имя \ что-то"
"\ server \ folderName1 \ другое имя \ something \ другая папка \"
(или отсортируйте полученную коллекцию по строке. Длина каждого значения.
Поймите, это старый пост, но я наткнулся на него, глядя - в конце концов, я решил использовать функцию ниже, поскольку она сортировала то, что я делал в то время, лучше, чем что-либо из вышеперечисленного:
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(new DirectoryInfo(di));
di = di.Parent;
}
rtn.Add(new DirectoryInfo(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 вместо простых строк полезно, если в дальнейшем вам потребуется взаимодействовать с папками.
Я реализовал более краткий метод ниже, вдохновленный вашим ответом.
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/// <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;
}
Я вижу ваш методВолк5370 и поднимаю вас.
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
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
Вот модификация ответа Вольфа, которая исключает корень и исправляет, казалось бы, пару ошибок. Я использовал его для создания панировочных сухарей, и я не хотел, чтобы корень отображался.
это расширение типа 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;
}
Я просто закодировал это, так как не нашел уже встроенных в 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;
}
На основе предыдущих ответов, но проще и без рекурсии. Кроме того, его не волнует, что такое символ разделения, поскольку 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. Пример использования:
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
Будьте осторожны, если вы хотите собрать массив обратно вместе с
Path.Combine, если у вас была буква диска в начале пути - это будет снова вместе какc:server\folderName1....