Encontre o número de arquivos com uma extensão específica, em todos os subdiretórios

StackOverflow https://stackoverflow.com/questions/27570

  •  09-06-2019
  •  | 
  •  

Pergunta

Existe uma maneira de encontrar o número de arquivos de um tipo específico sem precisar percorrer todos os resultados em um Directory.GetFiles() ou método semelhante?Estou procurando algo assim:

int ComponentCount = MagicFindFileCount(@"c:\windows\system32", "*.dll");

Eu sei que posso criar uma função recursiva para chamar Directory.GetFiles , mas seria muito mais limpo se pudesse fazer isso sem toda a iteração.

EDITAR: Se não for possível fazer isso sem recorrer e iterar, qual seria a melhor maneira de fazer isso?

Foi útil?

Solução

Você deve usar o Directory.GetFiles (caminho, searchPattern, SearchOption) sobrecarga de Directory.GetFiles().

Path especifica o caminho, searchPattern especifica seus curingas (por exemplo, *, *.format) e SearchOption fornece a opção de incluir subdiretórios.

A propriedade Length da matriz de retorno desta pesquisa fornecerá a contagem de arquivos adequada para seu padrão e opção de pesquisa específicos:

string[] files = directory.GetFiles(@"c:\windows\system32", "*.dll", SearchOption.AllDirectories);

return files.Length;

EDITAR: Alternativamente você pode usar Método Directory.EnumerateFiles

return Directory.EnumerateFiles(@"c:\windows\system32", "*.dll", SearchOption.AllDirectories).Count();

Outras dicas

O método mais inteligente seria usar linq:

var fileCount = (from file in Directory.EnumerateFiles(@"H:\iPod_Control\Music", "*.mp3", SearchOption.AllDirectories)
                    select file).Count();

Você pode usar esta sobrecarga de GetFiles:

Método Directory.getfiles (String, String, SearchOption)

e este membro do SearchOption:

Todos os diretórios - Inclui o diretório atual e todos os subdiretos em uma operação de pesquisa.Esta opção inclui pontos reparados, como unidades montadas e links simbólicos na pesquisa.

GetFiles retorna uma matriz de strings para que você possa obter apenas o comprimento, que é o número de arquivos encontrados.

Eu estava procurando uma versão mais otimizada.Como não encontrei, resolvi codificá-lo e compartilhá-lo aqui:

    public static int GetFileCount(string path, string searchPattern, SearchOption searchOption)
    {
        var fileCount = 0;
        var fileIter = Directory.EnumerateFiles(path, searchPattern, searchOption);
        foreach (var file in fileIter)
            fileCount++;
        return fileCount;
    }

Todas as soluções que usam GetFiles/GetDirectories são meio lentas, pois todos esses objetos precisam ser criados.Usando a enumeração, ela não cria nenhum objeto temporário (FileInfo/DirectoryInfo).

veja comentários http://msdn.microsoft.com/en-us/library/dd383571.aspx Para maiores informações

Usando recursão, seu MagicFindFileCount ficaria assim:

private int MagicFindFileCount( string strDirectory, string strFilter ) {
     int nFiles = Directory.GetFiles( strDirectory, strFilter ).Length;

     foreach( String dir in Directory.GetDirectories( strDirectory ) ) {
        nFiles += GetNumberOfFiles(dir, strFilter);
     }

     return nFiles;
  }

No entanto A solução de Jon pode ser o melhor.

Eu tenho um aplicativo que gera contagens de diretórios e arquivos em um diretório pai.Alguns dos diretórios contêm milhares de subdiretórios com milhares de arquivos em cada um.Para fazer isso enquanto mantenho uma interface de usuário responsiva, faço o seguinte (enviando o caminho para ADirectoryPath foi selecionado método):

public class DirectoryFileCounter
{
    int mDirectoriesToRead = 0;

    // Pass this method the parent directory path
    public void ADirectoryPathWasSelected(string path)
    {
        // create a task to do this in the background for responsive ui
        // state is the path
        Task.Factory.StartNew((state) =>
        {
            try
            {
                // Get the first layer of sub directories
                this.AddCountFilesAndFolders(state.ToString())


             }
             catch // Add Handlers for exceptions
             {}
        }, path));
    }

    // This method is called recursively
    private void AddCountFilesAndFolders(string path)
    {
        try
        {
            // Only doing the top directory to prevent an exception from stopping the entire recursion
            var directories = Directory.EnumerateDirectories(path, "*.*", SearchOption.TopDirectoryOnly);

            // calling class is tracking the count of directories
            this.mDirectoriesToRead += directories.Count();

            // get the child directories
            // this uses an extension method to the IEnumerable<V> interface,
           // which will run a function on an object. In this case 'd' is the 
           // collection of directories
            directories.ActionOnEnumerable(d => AddCountFilesAndFolders(d));
        }
        catch // Add Handlers for exceptions
        {
        }
        try
        {
            // count the files in the directory
            this.mFilesToRead += Directory.EnumerateFiles(path).Count();
        }
        catch// Add Handlers for exceptions
        { }
    }
}
// Extension class
public static class Extensions
{ 
    // this runs the supplied method on each object in the supplied enumerable
    public static void ActionOnEnumerable<V>(this IEnumerable<V> nodes,Action<V> doit)
    {

        foreach (var node in nodes)
        {   
            doit(node);
        }
    }
}

Alguém tem que fazer a parte da iteração.

AFAIK, esse método ainda não existe no .NET, então acho que alguém tem que ser você.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top