Список всех файлов и каталогов в каталоге + подкаталогах
Я хочу перечислить каждый файл и каталог, содержащиеся в каталоге и подкаталогах этого каталога. Если я выберу C:\ в качестве каталога, программа получит каждое имя каждого файла и папки на жестком диске, к которому у нее есть доступ.
Список может выглядеть так
FD \ 1.txt FD \2.txt FD \ а \ FD \ б \ FD \ а \ 1.txt FD \ а \2.txt FD \ а \ а \ FD \ а \ Ь \ FD \ б \ 1.txt FD \ б \2.txt FD \ б \ а FD \ б \ б FD \ а \ а \ 1.txt FD \ а \ а \ а \ FD \ а \ Ь \ 1.txt FD \ а \ Ь \ а FD \ Ь \ а \ 1.txt FD \ Ь \ а \ а \ FD \ б \ б \ 1.txt FD \ Ь \ Ь \ а
19 ответов
string[] allfiles = Directory.GetFiles("path/to/dir", "*.*", SearchOption.AllDirectories);
где *.*
шаблон для сопоставления файлов
Если Справочник также необходим, вы можете пойти так:
foreach (var file in allfiles){
FileInfo info = new FileInfo(file);
// Do something with the Folder or just add them to a list via nameoflist.add();
}
Directory.GetFileSystemEntries
существует в.NET 4.0+ и возвращает как файлы, так и каталоги. Назовите это так:
string[] entries = Directory.GetFileSystemEntries(path, "*", SearchOption.AllDirectories);
Обратите внимание, что он не справится с попытками составить список содержимого подкаталогов, к которым у вас нет доступа (UnauthorizedAccessException), но этого может быть достаточно для ваших нужд.
public static void DirectorySearch(string dir)
{
try
{
foreach (string f in Directory.GetFiles(dir))
{
Console.WriteLine(Path.GetFileName(f));
}
foreach (string d in Directory.GetDirectories(dir))
{
Console.WriteLine(Path.GetFileName(d));
DirectorySearch(d);
}
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Использовать GetDirectories
а также GetFiles
методы, чтобы получить папки и файлы.
Использовать SearchOption
AllDirectories
чтобы получить папки и файлы в подпапках также.
Я боюсь, что GetFiles
Метод возвращает список файлов, но не каталогов. Список в вопросе подсказывает мне, что результат должен включать и папки. Если вы хотите более индивидуальный список, вы можете попробовать позвонить GetFiles
а также GetDirectories
рекурсивно. Попробуй это:
List<string> AllFiles = new List<string>();
void ParsePath(string path)
{
string[] SubDirs = Directory.GetDirectories(path);
AllFiles.AddRange(SubDirs);
AllFiles.AddRange(Directory.GetFiles(path));
foreach (string subdir in SubDirs)
ParsePath(subdir);
}
Совет: вы можете использовать FileInfo
а также DirectoryInfo
классы, если вам нужно проверить какой-либо конкретный атрибут.
Поздний ответ, но я думаю, что кому-то это может пригодиться. Итеративный стартер версий на основе стека с поддержкой обработки ошибок и возврата относительных путей:
private static IEnumerable<string> TryEnumerate(Func<IEnumerable<string>> action)
{
try
{
return action.Invoke();
}
catch
{
//TODO logging
return Enumerable.Empty<string>();
}
}
private static IEnumerable<string> FindFilesAndDirectories(string dir, bool returnRelativePaths = false, string filePattern="*.*")
{
var searchStack = new Stack<string>();
searchStack.Push(dir);
var initialDirectory = new DirectoryInfo(dir).FullName;
var initialDirLength = initialDirectory.Length;
while (searchStack.Count > 0)
{
var currentDirectory = searchStack.Pop();
yield return (returnRelativePaths &&
string.Compare(currentDirectory, initialDirectory, StringComparison.OrdinalIgnoreCase) != 0) ?
currentDirectory.Substring(initialDirLength) : currentDirectory;
foreach (var file in TryEnumerate(() =>
Directory.EnumerateFiles(currentDirectory, filePattern)))
{
yield return returnRelativePaths ? file.Substring(initialDirLength) : file;
}
foreach (var directory in TryEnumerate(() =>
Directory.EnumerateDirectories(currentDirectory, filePattern)))
{
searchStack.Push(directory);
}
}
}
static void Main(string[] args)
{
foreach (var result in FindFilesAndDirectories(@"c:\", true))
{
Console.WriteLine(result);
}
}
Некоторая улучшенная версия с максимальным уровнем для перехода в каталог и возможностью исключения папок:
using System;
using System.IO;
class MainClass {
public static void Main (string[] args) {
var dir = @"C:\directory\to\print";
PrintDirectoryTree(dir, 2, new string[] {"folder3"});
}
public static void PrintDirectoryTree(string directory, int lvl, string[] excludedFolders = null, string lvlSeperator = "")
{
excludedFolders = excludedFolders ?? new string[0];
foreach (string f in Directory.GetFiles(directory))
{
Console.WriteLine(lvlSeperator+Path.GetFileName(f));
}
foreach (string d in Directory.GetDirectories(directory))
{
Console.WriteLine(lvlSeperator + "-" + Path.GetFileName(d));
if(lvl > 0 && Array.IndexOf(excludedFolders, Path.GetFileName(d)) < 0)
{
PrintDirectoryTree(d, lvl-1, excludedFolders, lvlSeperator+" ");
}
}
}
}
входной каталог:
-folder1
file1.txt
-folder2
file2.txt
-folder5
file6.txt
-folder3
file3.txt
-folder4
file4.txt
file5.txt
вывод функции (содержимое папки 5 исключено из-за ограничения lvl, а содержимое папки 3 исключено, потому что она находится в массиве excludedFolders):
-folder1
file1.txt
-folder2
file2.txt
-folder5
-folder3
-folder4
file4.txt
file5.txt
Вы можете использовать FindFirstFile, который возвращает дескриптор, а затем рекурсивно вызывать функцию, которая вызывает FindNextFile. Это хороший подход, так как указанная структура будет заполнена различными данными, такими как alternativeName,lastTmeCreated,modify, attribute и т. Д.
Но поскольку вы используете.net framework, вам придется входить в неуправляемую область.
Я использую следующий код с формой, которая имеет 2 кнопки, одну для выхода, а другую для запуска. Диалог браузера папки и диалог сохранения файла. Код указан ниже и работает в моей системе Windows10 (64):
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Directory_List
{
public partial class Form1 : Form
{
public string MyPath = "";
public string MyFileName = "";
public string str = "";
public Form1()
{
InitializeComponent();
}
private void cmdQuit_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void cmdGetDirectory_Click(object sender, EventArgs e)
{
folderBrowserDialog1.ShowDialog();
MyPath = folderBrowserDialog1.SelectedPath;
saveFileDialog1.ShowDialog();
MyFileName = saveFileDialog1.FileName;
str = "Folder = " + MyPath + "\r\n\r\n\r\n";
DirectorySearch(MyPath);
var result = MessageBox.Show("Directory saved to Disk!", "", MessageBoxButtons.OK);
Application.Exit();
}
public void DirectorySearch(string dir)
{
try
{
foreach (string f in Directory.GetFiles(dir))
{
str = str + dir + "\\" + (Path.GetFileName(f)) + "\r\n";
}
foreach (string d in Directory.GetDirectories(dir, "*"))
{
DirectorySearch(d);
}
System.IO.File.WriteAllText(MyFileName, str);
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
public static List<string> GetAllFilesInDirectory(string targetDirectory, List<string> list = null)
{
if (list == null)
{
list = new List<string>();
}
string[] fileEntries = Directory.GetFiles(targetDirectory);
foreach (string fileName in fileEntries)
{
list.Add(fileName);
}
string[] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
foreach (string subdirectory in subdirectoryEntries)
GetAllFilesInDirectory(subdirectory, list);
return list;
}
Логичный и упорядоченный способ:
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
namespace DirLister
{
class Program
{
public static void Main(string[] args)
{
//with reflection I get the directory from where this program is running, thus listing all files from there and all subdirectories
string[] st = FindFileDir(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location));
using ( StreamWriter sw = new StreamWriter("listing.txt", false ) )
{
foreach(string s in st)
{
//I write what I found in a text file
sw.WriteLine(s);
}
}
}
private static string[] FindFileDir(string beginpath)
{
List<string> findlist = new List<string>();
/* I begin a recursion, following the order:
* - Insert all the files in the current directory with the recursion
* - Insert all subdirectories in the list and rebegin the recursion from there until the end
*/
RecurseFind( beginpath, findlist );
return findlist.ToArray();
}
private static void RecurseFind( string path, List<string> list )
{
string[] fl = Directory.GetFiles(path);
string[] dl = Directory.GetDirectories(path);
if ( fl.Length>0 || dl.Length>0 )
{
//I begin with the files, and store all of them in the list
foreach(string s in fl)
list.Add(s);
//I then add the directory and recurse that directory, the process will repeat until there are no more files and directories to recurse
foreach(string s in dl)
{
list.Add(s);
RecurseFind(s, list);
}
}
}
}
}
Если у вас нет доступа к подпапке внутри дерева каталогов, Directory.GetFiles останавливается и выдает исключение, что приводит к нулевому значению в получающей строке [].
Вот, посмотрите этот ответ /questions/31684688/ignorirovat-papki-fajlyi-kogda-directorygetfiles-otkazano-v-dostupe/31684692#31684692
Он управляет исключением внутри цикла и продолжает работать до тех пор, пока не будет пройдена вся папка.
В следующем примере показан самый быстрый (не распараллеленный) способ списка файлов и подпапок в дереве каталогов, обрабатывающий исключения. Было бы быстрее использовать Directory.EnumerateDirectories с использованием SearchOption.AllDirectories для перечисления всех каталогов, но этот метод завершится ошибкой, если попадет в исключение UnauthorizedAccessException или PathTooLongException.
Использует универсальный тип коллекции стека, который является последним в стеке (LIFO) и не использует рекурсию. С https://msdn.microsoft.com/en-us/library/bb513869.aspx позволяет перечислять все подкаталоги и файлы и эффективно обрабатывать эти исключения.
public class StackBasedIteration
{
static void Main(string[] args)
{
// Specify the starting folder on the command line, or in
// Visual Studio in the Project > Properties > Debug pane.
TraverseTree(args[0]);
Console.WriteLine("Press any key");
Console.ReadKey();
}
public static void TraverseTree(string root)
{
// Data structure to hold names of subfolders to be
// examined for files.
Stack<string> dirs = new Stack<string>(20);
if (!System.IO.Directory.Exists(root))
{
throw new ArgumentException();
}
dirs.Push(root);
while (dirs.Count > 0)
{
string currentDir = dirs.Pop();
string[] subDirs;
try
{
subDirs = System.IO.Directory.EnumerateDirectories(currentDir); //TopDirectoryOnly
}
// An UnauthorizedAccessException exception will be thrown if we do not have
// discovery permission on a folder or file. It may or may not be acceptable
// to ignore the exception and continue enumerating the remaining files and
// folders. It is also possible (but unlikely) that a DirectoryNotFound exception
// will be raised. This will happen if currentDir has been deleted by
// another application or thread after our call to Directory.Exists. The
// choice of which exceptions to catch depends entirely on the specific task
// you are intending to perform and also on how much you know with certainty
// about the systems on which this code will run.
catch (UnauthorizedAccessException e)
{
Console.WriteLine(e.Message);
continue;
}
catch (System.IO.DirectoryNotFoundException e)
{
Console.WriteLine(e.Message);
continue;
}
string[] files = null;
try
{
files = System.IO.Directory.EnumerateFiles(currentDir);
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine(e.Message);
continue;
}
catch (System.IO.DirectoryNotFoundException e)
{
Console.WriteLine(e.Message);
continue;
}
// Perform the required action on each file here.
// Modify this block to perform your required task.
foreach (string file in files)
{
try
{
// Perform whatever action is required in your scenario.
System.IO.FileInfo fi = new System.IO.FileInfo(file);
Console.WriteLine("{0}: {1}, {2}", fi.Name, fi.Length, fi.CreationTime);
}
catch (System.IO.FileNotFoundException e)
{
// If file was deleted by a separate application
// or thread since the call to TraverseTree()
// then just continue.
Console.WriteLine(e.Message);
continue;
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine(e.Message);
continue;
}
}
// Push the subdirectories onto the stack for traversal.
// This could also be done before handing the files.
foreach (string str in subDirs)
dirs.Push(str);
}
}
}
строка path = @"D:"; строка [] allFiles = Directory.GetFiles(путь, ".", Море)
Пожалуйста, попробуйте приведенный ниже код, чтобы прочитать все каталоги и подкаталоги с файлами
class Program
{
static string _rootPath = @"D:\My Project\App_Data";
static void Main(string[] args)
{
ReadDirectories(_rootPath);
Console.ReadKey();
}
public static void ReadDirectories(string path, string directoryName = "")
{
if (!string.IsNullOrEmpty(directoryName))
{
Console.WriteLine("DIRECTORY NAME - {0}", directoryName);
path = @$"{path}\{directoryName}";
}
DirectoryInfo dir_place = new DirectoryInfo(path);
FileInfo[] Files = dir_place.GetFiles();
foreach (FileInfo i in Files)
{
Console.WriteLine("{0} - FILE NAME - {1}", directoryName, i.Name);
}
DirectoryInfo[] directories = dir_place.GetDirectories();
foreach (var directory in directories)
{
ReadDirectories(path, directory.Name);
};
}
}
Метод "ReadDirectories" вызывается до тех пор, пока не будет просканирован последний каталог.
Маленький бит медленно и медленно, но работает!! если вы не указали путь к файлу, в основном используйте "fixPath", это всего лишь пример.... вы можете найти правильный fileType, что вы хотите, я сделал ошибку, когда выбрал имя списка, потому что "временный_файл List - это список искомых файлов так что продолжайте.... и "errorList" говорит сам за себя
static public void Search(string path, string fileType, List<string> temporaryFileList, List<string> errorList)
{
List<string> temporaryDirectories = new List<string>();
//string fix = @"C:\Users\" + Environment.UserName + @"\";
string fix = @"C:\";
string folders = "";
//Alap útvonal megadása
if (path.Length != 0)
{ folders = path; }
else { path = fix; }
int j = 0;
int equals = 0;
bool end = true;
do
{
equals = j;
int k = 0;
try
{
int foldersNumber =
Directory.GetDirectories(folders).Count();
int fileNumber = Directory.GetFiles(folders).Count();
if ((foldersNumber != 0 || fileNumber != 0) && equals == j)
{
for (int i = k; k <
Directory.GetDirectories(folders).Length;)
{
temporaryDirectories.Add(Directory.GetDirectories(folders)[k]);
k++;
}
if (temporaryDirectories.Count == j)
{
end = false;
break;
}
foreach (string files in Directory.GetFiles(folders))
{
if (files != string.Empty)
{
if (fileType.Length == 0)
{
temporaryDirectories.Add(files);
}
else
{
if (files.Contains(fileType))
{
temporaryDirectories.Add(files);
}
}
}
else
{
break;
}
}
}
equals++;
for (int i = j; i < temporaryDirectories.Count;)
{
folders = temporaryDirectories[i];
j++;
break;
}
}
catch (Exception ex)
{
errorList.Add(folders);
for (int i = j; i < temporaryDirectories.Count;)
{
folders = temporaryDirectories[i];
j++;
break;
}
}
} while (end);
}
При этом вы можете просто запустить их и выбрать подпапку при запуске консоли.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using data.Patcher; // The patcher XML
namespace PatchBuilder
{
class Program
{
static void Main(string[] args)
{
string patchDir;
if (args.Length == 0)
{
Console.WriteLine("Give the patch directory in argument");
patchDir = Console.ReadLine();
}
else
{
patchDir = args[0];
}
if (File.Exists(Path.Combine(patchDir, "patch.xml")))
File.Delete(Path.Combine(patchDir, "patch.xml"));
var files = Directory.EnumerateFiles(patchDir, "*", SearchOption.AllDirectories).OrderBy(p => p).ToList();
foreach (var file in files.Where(file => file.StartsWith("patch\\Resources")).ToArray())
{
files.Remove(file);
files.Add(file);
}
var tasks = new List<MetaFileEntry>();
using (var md5Hasher = MD5.Create())
{
for (int i = 0; i < files.Count; i++)
{
var file = files[i];
if ((File.GetAttributes(file) & FileAttributes.Hidden) != 0)
continue;
var content = File.ReadAllBytes(file);
var md5Hasher2 = MD5.Create();
var task =
new MetaFileEntry
{
LocalURL = GetRelativePath(file, patchDir + "\\"),
RelativeURL = GetRelativePath(file, patchDir + "\\"),
FileMD5 = Convert.ToBase64String(md5Hasher2.ComputeHash(content)),
FileSize = content.Length,
};
md5Hasher2.Dispose();
var pathBytes = Encoding.UTF8.GetBytes(task.LocalURL.ToLower());
md5Hasher.TransformBlock(pathBytes, 0, pathBytes.Length, pathBytes, 0);
if (i == files.Count - 1)
md5Hasher.TransformFinalBlock(content, 0, content.Length);
else
md5Hasher.TransformBlock(content, 0, content.Length, content, 0);
tasks.Add(task);
Console.WriteLine(@"Add " + task.RelativeURL);
}
var patch = new MetaFile
{
Tasks = tasks.ToArray(),
FolderChecksum = BitConverter.ToString(md5Hasher.Hash).Replace("-", "").ToLower(),
};
//XmlUtils.Serialize(Path.Combine(patchDir, "patch.xml"), patch);
Console.WriteLine(@"Created Patch in {0} !", Path.Combine(patchDir, "patch.xml"));
}
Console.Read();
}
static string GetRelativePath(string fullPath, string relativeTo)
{
var foldersSplitted = fullPath.Split(new[] { relativeTo.Replace("/", "\\").Replace("\\\\", "\\") }, StringSplitOptions.RemoveEmptyEntries); // cut the source path and the "rest" of the path
return foldersSplitted.Length > 0 ? foldersSplitted.Last() : ""; // return the "rest"
}
}
}
и это патчар для экспорта XML
using System.Xml.Serialization;
namespace data.Patcher
{
public class MetaFile
{
[XmlArray("Tasks")]
public MetaFileEntry[] Tasks
{
get;
set;
}
[XmlAttribute("checksum")]
public string FolderChecksum
{
get;
set;
}
}
}
Создать список строк
public static List<string> HTMLFiles = new List<string>();
private void Form1_Load(object sender, EventArgs e)
{
HTMLFiles.AddRange(Directory.GetFiles(@"C:\DataBase", "*.txt"));
foreach (var item in HTMLFiles)
{
MessageBox.Show(item);
}
}
using System.IO;
using System.Text;
string[] filePaths = Directory.GetFiles(@"path", "*.*", SearchOption.AllDirectories);