Je veux lister tous les fichiers et répertoires contenus dans un répertoire et des sous-répertoires de ce répertoire. Si je choisis C:\comme répertoire, le programme obtiendra tous les noms de tous les fichiers et dossiers du disque dur auxquels il a accès.
Une liste pourrait ressembler à
fd\1.txt fd\2txt fd\a\a\ fd\a\b\ fd\b\1.txt fd\b\2.txt \b\b fd\a\a\1.txt fd\a\a\a\.__ fd\a\b\1.txt fd\a\b\a fd\b\a\1.txt fd\b\a\ fd\b\b\1.txt fd\b\b\a
string[] allfiles = Directory.GetFiles("path/to/dir", "*.*", SearchOption.AllDirectories);
où *.*
est le motif pour faire correspondre les fichiers
Si le répertoire est également nécessaire, vous pouvez procéder comme suit:
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
existe dans .NET 4.0+ et renvoie les fichiers et les répertoires. Appelez ça comme ça:
string[] entries = Directory.GetFileSystemEntries(path, "*", SearchOption.AllDirectories);
Notez que cela ne résoudra pas les tentatives de liste du contenu des sous-répertoires auxquels vous n’avez pas accès (UnauthorizedAccessException), mais cela peut suffire à vos besoins.
Utilisez les méthodes GetDirectories
et GetFiles
pour obtenir les dossiers et les fichiers.
Utilisez SearchOption
AllDirectories
pour obtenir également les dossiers et les fichiers des sous-dossiers.
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);
}
}
Je crains que la méthode GetFiles
ne renvoie la liste des fichiers mais pas les répertoires. La liste de la question m'invite à indiquer que le résultat devrait également inclure les dossiers. Si vous souhaitez une liste plus personnalisée, vous pouvez essayer d'appeler GetFiles
et GetDirectories
de manière récursive. Essaye ça:
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);
}
Conseil: Vous pouvez utiliser les classes FileInfo
et DirectoryInfo
si vous devez vérifier un attribut spécifique.
Vous pouvez utiliser FindFirstFile, qui renvoie un descripteur, puis une fonction qui appelle FindNextFile de manière récursive. C’est une bonne approche car la structure référencée serait remplie avec diverses données telles que alternativeName, lastTmeCreated, modifié, etc.
Mais lorsque vous utilisez le framework .net, vous devez entrer dans la zone non gérée.
J'utilise le code suivant avec un formulaire qui a 2 boutons, un pour quitter et l'autre pour commencer. Un dialogue de navigateur de dossier et un dialogue de sauvegarde de fichier. Le code est répertorié ci-dessous et fonctionne sur mon système 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);
}
}
}
}
L'exemple suivant illustre la manière dont est plus rapide (] non parallélisé) répertorie les fichiers et les sous-dossiers d'une arborescence de répertoires gérant des exceptions. Il serait plus rapide d'utiliser Directory.EnumerateDirectories à l'aide de SearchOption.AllDirectories pour énumérer tous les répertoires, mais cette méthode échouera si une exception UnauthorizedAccessException ou PathTooLongException est rencontrée.
Utilise le type de collection Stack générique, qui correspond à une pile de type dernier entré, premier sorti (LIFO) et n'utilise pas de récursivité. From https://msdn.Microsoft.com/en-us/library/bb513869.aspx , vous permet d'énumérer tous les sous-répertoires et fichiers et de gérer efficacement ces exceptions.
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);
}
}
}
la manière logique et ordonnée:
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);
}
}
}
}
}
Si vous n'avez pas accès à un sous-dossier de l'arborescence de répertoires, Directory.GetFiles s'arrête et lève l'exception, ce qui entraîne une valeur null dans la chaîne de réception [].
Voir ici la réponse https://stackoverflow.com/a/38959208/6310707
Il gère l'exception à l'intérieur de la boucle et continue à fonctionner jusqu'à ce que tout le dossier soit parcouru.