Lista todos os arquivos e diretórios em um diretório + subdiretórios


109

Quero listar todos os arquivos e diretórios contidos em um diretório e subdiretórios desse diretório. Se eu escolher C: \ como o diretório, o programa obterá todos os nomes de todos os arquivos e pastas do disco rígido aos quais tenha acesso.

Uma lista pode parecer

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

Navegue no namespace System.IO para classes e métodos que podem ajudá-lo.
Lucero

Confira esta pergunta e deixe a parte em que ele está correspondendo a um padrão.
dasblinkenlight

Respostas:


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

onde *.*está o padrão para combinar os arquivos

Se o diretório também for necessário, você pode proceder assim:

 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
Realmente não vai funcionar ... Lsit<>classe? O que GetFiles retorna? E os nomes dos diretórios que também foram solicitados?
Lucero

1
O GetFilesmétodo retorna uma matriz de string.
Guffa

actualy ... você está certo ... Estou aprendendo Qt abaout 2 dias atrás e foi um pouco equivocada
Ruslan F.

Isso pode funcionar, mas geralmente falha com um UnauthorizedAccessException. Como pesquisaria apenas os diretórios que ele pode acessar?
derp_in_mouth

isso significa que em seu sistema este aplicativo não tem permissões suficientes
Ruslan F.

50

Directory.GetFileSystemEntriesexiste no .NET 4.0+ e retorna arquivos e diretórios. Chame assim:

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

Observe que não vai lidar com as tentativas de listar o conteúdo de subdiretórios aos quais você não tem acesso (UnauthorizedAccessException), mas pode ser suficiente para suas necessidades.


3
Esta é de longe a melhor resposta aqui. Ele obtém todos os arquivos e pastas em uma linha de código, o que nenhum dos outros faz.
Steve Smith

15

Use os métodos GetDirectoriese GetFilespara obter as pastas e arquivos.

Use para obter as pastas e arquivos nas subpastas também.SearchOption AllDirectories


Use Substring para cortar a parte esquerda do nome. :)
Lucero

@Lucero Como e por que você faria isso? Pathoferece métodos mais confiáveis.
Gusdor

@Gusdor Sinta-se à vontade para sugerir uma maneira mais adequada usando o Pathpara remover uma parte esquerda fixa do caminho, por exemplo, `C:` no exemplo dado.
Lucero

@Lucero meu comentário foi mal formulado. 'Usar substring' não me diz muito e eu tive que ficar preso ao linqpad para derivar uma boa solução. Por exemplo, qual seria o parâmetro? Você vai fazer path.SubString(2)para remover ingenuamente a letra da unidade e dois pontos? E se o diretório for um compartilhamento de rede? Eu o sugiro Pathcomo um método confiável porque pode fornecer muitos benefícios nesta área. Neste caso, você pode escrever filePath.Substring(Path.GetPathRoot(filePath).Length). Sim, ele usa Substring, pois é o mais 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
Melhoraria sua resposta se você pudesse adicionar uma pequena explicação do que o código faz.
Alex de

Ele passa recursivamente pelo diretório e imprime nomes de arquivos ou de diretórios. Para cada diretório interno, ele chama a mesma função. Para mais informações: stackoverflow.com/questions/929276/…
I.Step

3

Infelizmente, o GetFilesmétodo retorna a lista de arquivos, mas não os diretórios. A lista da pergunta indica que o resultado também deve incluir as pastas. Se você quiser uma lista mais personalizada, pode tentar ligar GetFilese GetDirectoriesrecursivamente. Experimente isto:

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

Dica: Você pode usar as classes FileInfoe DirectoryInfose precisar verificar algum atributo específico.


1

Você pode usar FindFirstFile que retorna um identificador e, em seguida, chamar recursivamente uma função que chama FindNextFile. Esta é uma boa abordagem, pois a estrutura referenciada seria preenchida com vários dados, como alternativeName, lastTmeCreated, modificado, atributos etc.

Mas ao usar o framework .net, você teria que entrar na área não gerenciada.


1

Alguma versão melhorada com lvl máximo para descer no diretório e opção para excluir pastas:

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

diretório de entrada:

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

saída da função (o conteúdo da pasta5 é excluído devido ao limite de lvl e o conteúdo da pasta3 é excluído porque está na matriz excludedFolders):

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

0

Se você não tiver acesso a uma subpasta dentro da árvore de diretórios, Directory.GetFiles para e lança a exceção, resultando em um valor nulo na string de recebimento [].

Aqui, veja esta resposta https://stackoverflow.com/a/38959208/6310707

Ele gerencia a exceção dentro do loop e continua trabalhando até que toda a pasta seja percorrida.


0

a maneira lógica e 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);
            }
        }
    }
}
}

Você poderia fornecer uma explicação ou comentários in-line, o que seu código faz?
MarthyM de

claro, fiz isso, mas deve ser autoexplicativo, é uma recursão simples em loop por todos os diretórios e arquivos
Sascha

0

O exemplo a seguir é a maneira mais rápida (não paralelizada) de listar arquivos e subpastas em uma árvore de diretório que trata as exceções. Seria mais rápido usar Directory.EnumerateDirectories usando SearchOption.AllDirectories para enumerar todos os diretórios, mas este método falhará se atingir UnauthorizedAccessException ou PathTooLongException.

Usa o tipo de coleção Stack genérico, que é uma pilha LIFO (last in first out) e não usa recursão. Em https://msdn.microsoft.com/en-us/library/bb513869.aspx , permite enumerar todos os subdiretórios e arquivos e lidar efetivamente com essas exceções.

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

Usando o Google Tarefas para arquivos e diretórios com grande número de arquivos?
PreguntonCojoneroCabrón

msdn.microsoft.com/en-us/library/ff477033(v=vs.110).aspx é a versão Parallel Threading da solução acima usando uma coleção de pilha e mais rápida.
Markus

0

Eu uso o seguinte código com um formulário que possui 2 botões, um para sair e outro para iniciar. Uma caixa de diálogo do navegador de pasta e uma caixa de diálogo para salvar arquivo. O código está listado abaixo e funciona no meu 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);
            }
        }
    }
}

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

Sua resposta não acrescenta nada de novo a uma resposta votada anteriormente.
localidade padrão

1
Também está errado, já que não retorna nenhum diretório (como a questão especifica), apenas arquivos reais.
Alastair Maw

-1

Um pouco simples e devagar, mas funcionando !! se você não fornecer um caminho de arquivo, use basicamente o "fixPath" este é apenas um exemplo .... você pode pesquisar o tipo de arquivo correto que você deseja, cometi um erro ao escolher o nome da lista porque o "TemporaryFileList é a lista de arquivos pesquisada então continue ... e o "errorList" fala por si

 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

Criar lista de string

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

}

Isso não obtém subdiretórios.
TidyDev

-1

dir / s / b . > resultados.txt

/ s = subpastas / b = resultados do urso

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.