Finden Sie die Anzahl der Dateien mit einer bestimmten Erweiterung in allen Unterverzeichnissen

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

  •  09-06-2019
  •  | 
  •  

Frage

Gibt es eine Möglichkeit, die Anzahl der Dateien eines bestimmten Typs zu ermitteln, ohne alle Ergebnisse in einer Directory.GetFiles() oder einer ähnlichen Methode durchlaufen zu müssen?Ich suche so etwas:

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

Ich weiß, dass ich eine rekursive Funktion zum Aufrufen von Directory.GetFiles erstellen kann, aber es wäre viel sauberer, wenn ich dies ohne all die Iterationen tun könnte.

BEARBEITEN: Wenn es nicht möglich ist, dies zu tun, ohne sich selbst zu rekursieren und zu iterieren, was wäre dann der beste Weg, dies zu tun?

War es hilfreich?

Lösung

Sie sollten das verwenden Directory.GetFiles(Pfad, Suchmuster, Suchoption) Überladung von Directory.GetFiles().

Path gibt den Pfad an, searchPattern gibt Ihre Platzhalter an (z. B. *, *.format) und SearchOption bietet die Option, Unterverzeichnisse einzubeziehen.

Die Eigenschaft „Length“ des Rückgabearrays dieser Suche liefert die richtige Dateianzahl für Ihr spezielles Suchmuster und Ihre Option:

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

return files.Length;

BEARBEITEN: Alternativ können Sie verwenden Directory.EnumerateFiles-Methode

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

Andere Tipps

Die raffinierteste Methode wäre die Verwendung von Linq:

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

Sie können diese Überladung von GetFiles verwenden:

Verzeichnis.getFiles -Methode (String, String, Searchoption)

und dieses Mitglied von SearchOption:

Alle Verzeichnisse - Enthält das aktuelle Verzeichnis und alle Unterverzeichnisse in einer Suchoperation.Diese Option umfasst Reparaturpunkte wie montierte Laufwerke und symbolische Links in der Suche.

GetFiles gibt ein String-Array zurück, sodass Sie einfach die Länge ermitteln können, die der Anzahl der gefundenen Dateien entspricht.

Ich war auf der Suche nach einer optimierteren Version.Da ich es nicht gefunden habe, habe ich beschlossen, es zu codieren und hier zu teilen:

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

Alle Lösungen, die GetFiles/GetDirectories verwenden, sind etwas langsam, da alle diese Objekte erstellt werden müssen.Mithilfe der Enumeration werden keine temporären Objekte (FileInfo/DirectoryInfo) erstellt.

Siehe Bemerkungen http://msdn.microsoft.com/en-us/library/dd383571.aspx für mehr Informationen

Bei Verwendung der Rekursion würde Ihr MagicFindFileCount so aussehen:

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

Obwohl Jons Lösung könnte das bessere sein.

Ich habe eine App, die die Anzahl der Verzeichnisse und Dateien in einem übergeordneten Verzeichnis generiert.Einige der Verzeichnisse enthalten Tausende von Unterverzeichnissen mit jeweils Tausenden von Dateien.Um dies zu tun und gleichzeitig eine reaktionsfähige Benutzeroberfläche beizubehalten, gehe ich wie folgt vor (sende den Pfad an ADirectoryPathWasSelected Methode):

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

Jemand muss den iterierenden Teil übernehmen.

AFAIK, in .NET gibt es noch keine solche Methode, also vermute ich, dass jemand Sie sein müssen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top