Monitoring the Size of a Folder

In this article, we’ll develop a simple application that can check the total size taken by a folder (including the files directly inside it, and those in its subfolders), and monitor it periodically to send alerts if it exceeds a certain threshold. This can be useful, for example, to ensure that automatic backups aren’t taking too much space on disk. The source code is available at the Gigi Labs BitBucket repository.

The techniques we’ll use for this are nothing new. We’ll use recursive directory traversal to calculate the total size of the folder, and we’ll use a timer to check this periodically. To send alerts, we’d typically use SmtpClient to send email, but since you’d need an actual SMTP server to test this, we’ll just write something to the console instead.

We’ll start off by calculating the total size of a folder:

        static void Main(string[] args)
        {
            string directoryPath = ConfigurationManager.AppSettings["DirectoryPath"];

            var dir = new DirectoryInfo(directoryPath);
            var size = CalculateDirectorySize(dir);
            Console.WriteLine(size);

            Console.ReadKey(true);
        }

We’re reading the path to the directory to monitor from an application setting (remember to add a reference to System.Configuration). Then we pass the resulting DirectoryInfo object to a recursive CalculateDirectorySize() method, which we’ll define next:

        static long CalculateDirectorySize(DirectoryInfo dir)
        {
            long totalSize = 0L;

            foreach (var file in dir.EnumerateFiles())
                totalSize += file.Length;

            foreach (var subdir in dir.EnumerateDirectories())
                totalSize += CalculateDirectorySize(subdir);

            return totalSize;
        }

This recursive method simply adds up the sizes of the files it contains directly, then adds the total size after recursing into its subdirectories. We’re using the long data type because int will overflow if the folder contains several gigabytes of data.

Note: you might get an UnauthorizedAccessException if you run this in something like C:. It’s easiest to just run it on a folder within your user folder.

This is the result of running the above code against my desktop (which I seem to need to clean up):

dirsize-desktop

We can now refactor our Main() method to run a timer and periodically check the size of the folder:

        private static string directoryPath;

        static void Main(string[] args)
        {
            directoryPath = ConfigurationManager.AppSettings["DirectoryPath"];

            var timer = new Timer();
            timer.Interval = 5000;
            timer.Elapsed += Timer_Elapsed;
            timer.Enabled = true;
            timer.Start();

            Console.ReadKey(true);
        }

Every 5 seconds, the timer will run the following event handler:

        private static void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            var dir = new DirectoryInfo(directoryPath);
            var size = CalculateDirectorySize(dir);
            Console.WriteLine(size);
        }

It is now very easy to extend this with a warning mechanism:

        private static string directoryPath;
        private static long threshold;

        static void Main(string[] args)
        {
            directoryPath = ConfigurationManager.AppSettings["DirectoryPath"];
            threshold = Convert.ToInt64(ConfigurationManager.AppSettings["Threshold"]);

            var timer = new Timer();
            timer.Interval = 5000;
            timer.Elapsed += Timer_Elapsed;
            timer.Enabled = true;
            timer.Start();

            Console.ReadKey(true);
        }

        private static void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            var dir = new DirectoryInfo(directoryPath);
            var size = CalculateDirectorySize(dir);
            string warning = size > threshold ? " WARNING - THRESHOLD EXCEEDED" : null;
            Console.WriteLine("{0}{1}", size, warning);
        }

Here’s an example run of this application:

dirsize-warnings

Add to that some exception handling and console title code, and you get the source code available in the Gigi Labs BitBucket repository.