Enumere todos los archivos y directorios en un directorio + subdirectorios


109

Quiero enumerar todos los archivos y directorios contenidos en un directorio y subdirectorios de ese directorio. Si elijo C: \ como directorio, el programa obtendría todos los nombres de todos los archivos y carpetas del disco duro al que tenía acceso.

Una lista puede verse como

fd \ 1.txt
fd \ 2.txt
fd \ a \
fd \ b \
fd \ a \ 1.txt
fd \ a \ 2.txt
fd \ a \ a \
fd \ a \ b \
fd \ b \ 1.txt
fd \ b \ 2.txt
fd \ b \ a
fd \ 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 \ a \
fd \ b \ b \ 1.txt
fd \ b \ b \ a

Explore el espacio de nombres System.IO en busca de clases y métodos que puedan ayudarlo.
Lucero

Mira esta pregunta y suelta la parte en la que coincide con un patrón.
dasblinkenlight

Respuestas:


192
string[] allfiles = Directory.GetFiles("path/to/dir", "*.*", SearchOption.AllDirectories);

dónde *.*está el patrón para hacer coincidir los archivos

Si el directorio también es necesario, puede hacer lo siguiente:

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

1
¿No funcionará realmente ... Lsit<>clase? ¿Qué devuelve GetFiles? ¿Y los nombres de los directorios que también se solicitaron?
Lucero

1
El GetFilesmétodo devuelve una matriz de cadenas.
Guffa

en realidad ... tienes razón ... estoy aprendiendo Qt hace aproximadamente 2 días y me equivoqué un poco
Ruslan F.

Esto podría funcionar, pero a menudo falla con una UnauthorizedAccessException. ¿Cómo buscaría solo los directorios a los que puede acceder?
derp_in_mouth

significa que en su sistema esta aplicación no tiene suficientes permisos
Ruslan F.

50

Directory.GetFileSystemEntriesexiste en .NET 4.0+ y devuelve tanto archivos como directorios. Llámalo así:

string[] entries = Directory.GetFileSystemEntries(path, "*", SearchOption.AllDirectories);

Tenga en cuenta que no podrá hacer frente a los intentos de enumerar el contenido de los subdirectorios a los que no tiene acceso (UnauthorizedAccessException), pero puede ser suficiente para sus necesidades.


3
Esta es, con mucho, la mejor respuesta aquí. Obtiene todos los archivos y carpetas en una línea de código, lo que no hace ninguno de los demás.
Steve Smith

15

Utilice los métodos GetDirectoriesy GetFilespara obtener las carpetas y los archivos.

Utilice para obtener las carpetas y archivos en las subcarpetas también.SearchOption AllDirectories


Utilice Substring para cortar la parte izquierda del nombre. :)
Lucero

@Lucero ¿Cómo y por qué harías eso? Pathofrece métodos más fiables.
Gusdor

@Gusdor Siéntase libre de sugerir una forma más adecuada usando el Pathpara eliminar una parte izquierda fija de la ruta, por ejemplo, `C:` en el ejemplo dado.
Lucero

@Lucero mi comentario fue mal redactado. 'Usar subcadena' no me dice mucho y tuve que quedarme atascado en linqpad para obtener una buena solución. Por ejemplo, ¿cuál sería el parámetro? ¿Vas a hacer path.SubString(2)para eliminar ingenuamente la letra de unidad y los dos puntos? ¿Qué pasa si el directorio es un recurso compartido de red? Sugiero Pathcomo un método confiable porque puede proporcionar un montón de golosinas en esta área. En este caso, puede escribir filePath.Substring(Path.GetPathRoot(filePath).Length). Sí, esto usa Substring ya que es el más conciso.
Gusdor

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

3
Mejoraría su respuesta si pudiera agregar una pequeña explicación de lo que hace el código.
Alex

Recorre el directorio de forma recursiva e imprime nombres de archivos o directorios. Para cada directorio interno, llama a la misma función. Para obtener más información: stackoverflow.com/questions/929276/…
I.Step

3

Me temo que el GetFilesmétodo devuelve una lista de archivos pero no los directorios. La lista de la pregunta me indica que el resultado también debe incluir las carpetas. Si desea una lista más personalizada, puede intentar llamar GetFilesy de forma GetDirectoriesrecursiva. Prueba esto:

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

Sugerencia: puede usar las clases FileInfoy DirectoryInfosi necesita verificar algún atributo específico.


1

Puede usar FindFirstFile que devuelve un identificador y luego llamar de forma recursiva a una función que llama a FindNextFile. Este es un buen enfoque ya que la estructura a la que se hace referencia se rellenaría con varios datos como AlternativeName, lastTmeCreated, modified, atributos, etc.

Pero a medida que usa .net framework, tendría que ingresar al área no administrada.


1

Alguna versión mejorada con max lvl para bajar en el directorio y la opción de excluir carpetas:

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+"  ");
        }
    }
  }
}

directorio de entrada:

-folder1
  file1.txt
  -folder2
    file2.txt
    -folder5
      file6.txt
  -folder3
    file3.txt
  -folder4
    file4.txt
    file5.txt

salida de la función (el contenido de la carpeta 5 se excluye debido al límite de nivel y el contenido de la carpeta 3 se excluye porque está en la matriz de carpetas excluidas):

-folder1
  file1.txt
  -folder2
    file2.txt
    -folder5
  -folder3
  -folder4
    file4.txt
    file5.txt

0

Si no tiene acceso a una subcarpeta dentro del árbol de directorios, Directory.GetFiles se detiene y lanza la excepción que da como resultado un valor nulo en la cadena de recepción [].

Aquí, vea esta respuesta https://stackoverflow.com/a/38959208/6310707

Gestiona la excepción dentro del bucle y sigue funcionando hasta que se atraviesa toda la carpeta.


0

la forma lógica y ordenada:

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

¿Podría proporcionar una explicación o comentarios en línea, qué hace su código?
MarthyM

por supuesto, lo hice, pero debería explicarse por sí mismo, es una recursión simple en bucle a través de todos los directorios y archivos
Sascha

0

El siguiente ejemplo es el más rápido (no paralelizada) de archivos y subcarpetas en un árbol de directorios que maneja excepciones. Sería más rápido usar Directory.EnumerateDirectories usando SearchOption.AllDirectories para enumerar todos los directorios, pero este método fallará si llega a UnauthorizedAccessException o PathTooLongException.

Utiliza el tipo de colección Stack genérico, que es una pila de último en entrar, primero en salir (LIFO) y no utiliza la recursividad. Desde https://msdn.microsoft.com/en-us/library/bb513869.aspx , le permite enumerar todos los subdirectorios y archivos y tratar de manera efectiva esas excepciones.

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

¿Utiliza Tareas para grandes cantidades de archivos y directorios?
PreguntonCojoneroCabrón

msdn.microsoft.com/en-us/library/ff477033(v=vs.110).aspx es la versión Parallel Threading de la solución anterior que usa una colección de pila y más rápido.
Markus

0

Utilizo el siguiente código con un formulario que tiene 2 botones, uno para salir y el otro para comenzar. Un cuadro de diálogo del navegador de carpetas y un cuadro de diálogo para guardar archivo. El código se enumera a continuación y funciona en mi sistema 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);
            }
        }
    }
}

0

Con esto, puede ejecutarlos y elegir la subcarpeta cuando se ejecuta la consola

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

y este es el patchar para la exportación 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;
        }
    }
}

-1
using System.IO;
using System.Text;
string[] filePaths = Directory.GetFiles(@"path", "*.*", SearchOption.AllDirectories);

Su respuesta no agrega nada nuevo a una respuesta más votada ya existente.
configuración regional predeterminada

1
También está mal, ya que esto no devuelve ningún directorio (como se especifica en la pregunta), solo archivos reales.
Alastair Maw

-1

Un poco simple y lento pero funcionando !! si no proporciona una ruta de archivo, utilice básicamente el "fixPath", esto es solo un ejemplo ... puede buscar el archivo correcto, escriba lo que desee, cometí un error cuando elegí el nombre de la lista porque "temporaryFileList es la lista de archivos buscados así que continúa con eso ... y el "errorList" habla por sí mismo

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

-1

Crear lista de cadena

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

}

Esto no obtiene subdirectorios.
TidyDev

-1

dir / s / b . > resultados.txt

/ s = subcarpetas / b = resultados de oso

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.