How do I get a directory size (files in the directory) in C#?

A very succinct way to get a folder size in .net 4.0 is below. It still suffers from the limitation of having to traverse all files recursively, but it doesn't load a potentially huge array of filenames, and it's only two lines of code. Make sure to use the namespaces System.IO and System.Linq.

private static long GetDirectorySize(string folderPath)
{
    DirectoryInfo di = new DirectoryInfo(folderPath);
    return di.EnumerateFiles("*.*", SearchOption.AllDirectories).Sum(fi => fi.Length);
}

If you use Directory.GetFiles you can do a recursive seach (using SearchOption.AllDirectories), but this is a bit flaky anyway (especially if you don't have access to one of the sub-directories) - and might involve a huge single array coming back (warning klaxon...).

I'd be happy with the recursion approach unless I could show (via profiling) a bottleneck; and then I'd probably switch to (single-level) Directory.GetFiles, using a Queue<string> to emulate recursion.

Note that .NET 4.0 introduces some enumerator-based file/directory listing methods which save on the big arrays.


You could hide your recursion behind an extension method (to avoid the issues Marc has highlighted with the GetFiles() method):

public static class UserExtension
{
  public static IEnumerable<FileInfo> Walk(this DirectoryInfo directory)
  {
    foreach(FileInfo file in directory.GetFiles())
    {
      yield return file;
    }

    foreach(DirectoryInfo subDirectory in directory.GetDirectories())
    { 
      foreach(FileInfo file in subDirectory.Walk())
      {
        yield return file;
      }
    }
  }
}

(You probably want to add some exception handling to this for protected folders etc.)

Then:

using static UserExtension;

long totalSize = 0L;
var startFolder = new DirectoryInfo("<path to folder>");

// iteration
foreach(FileInfo file in startFolder.Walk())
{
    totalSize += file.Length;
}

// linq
totalSize = di.Walk().Sum(s => s.Length);

Basically the same code, but maybe a little neater...


Here my .NET 4.0 approach

public static long GetFileSizeSumFromDirectory(string searchDirectory)
{
 var files = Directory.EnumerateFiles(searchDirectory);

 // get the sizeof all files in the current directory
 var currentSize = (from file in files let fileInfo = new FileInfo(file) select fileInfo.Length).Sum();

 var directories = Directory.EnumerateDirectories(searchDirectory);

 // get the size of all files in all subdirectories
 var subDirSize = (from directory in directories select GetFileSizeSumFromDirectory(directory)).Sum();

 return currentSize + subDirSize;
}

Or even nicer:

// get IEnumerable from all files in the current dir and all sub dirs
var files = Directory.EnumerateFiles(searchDirectory,"*",SearchOption.AllDirectories);

// get the size of all files
long sum = (from file in files let fileInfo = new FileInfo(file) select fileInfo .Length).Sum();

As Gabriel pointed out this will fail if you have a restricted directory under the searchDirectory!