1

This question may seem a bit absurd but here goes..

I have a directory structure: It has 8 levels. So, for example this is 1 path:

C:\Root\Catalogue\000EC902F17F\2\2013\11\15\13

The '2' is an index for a webcam. I have 4 in total. so..

C:\Root\Catalogue\000EC902F17F\1\2013\11\15\13
C:\Root\Catalogue\000EC902F17F\2\2013\11\15\13
C:\Root\Catalogue\000EC902F17F\3\2013\11\15\13
C:\Root\Catalogue\000EC902F17F\4\2013\11\15\13

The '000EC902F17F' is my own uuid for my webcam.

The '2013' is the year.
The '11' is the month.
The '13' is the day.

When I capture motion the jpegs are saved in a directory that signifies when that image was captured.

I have a timer that goes through each directory and create a video file from the images. The images are then deleted.

Now, I want to have another timer that will go through each directory to check for empty directories. If they are empty the folder is deleted.

This tidy-up timer will look at directories created that are older than the current day it runs.

I presently have this:

private List<string> GetFoldersToDelete()
{
    DateTime to_date = DateTime.Now.AddDays(-1);
    List<string> paths = Directory.EnumerateDirectories(@"C:\MotionWise\Catalogue\" + Shared.ActiveMac, "*", SearchOption.AllDirectories)
        .Where(path =>
        {
            DateTime lastWriteTime = File.GetLastWriteTime(path);
            return lastWriteTime <= to_date;
        })
        .ToList();
    return paths;
}

called by:

        List<string> _deleteMe = new List<string>();
        List<string> _folders2Delete = GetFoldersToDelete();
        foreach (string _folder in _folders2Delete)
        {
           List<string> _folderContents = Directory.EnumerateFiles(_folder).ToList();
           if (_folderContents.Count == 0)
           {
               _folders2Delete.Add(_folder);
           }
        }
        for (int _index = 0; _index < _folders2Delete.Count; _index++)
        {
            Directory.Delete(_folders2Delete[_index];
        }

Is there a better way to achieve what I want?

Andrew Simpson
  • 6,883
  • 11
  • 79
  • 179
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Nov 15 '13 at 14:27
  • Hi John, thanks for that link. I will read it now – Andrew Simpson Nov 15 '13 at 14:28
  • I would model a solution after this answer to a similar question: http://stackoverflow.com/a/8143457/240313 – Joel Rondeau Nov 15 '13 at 14:31
  • @JoelRondeau Hi, thanks for that link. I read somewhere (cannot remember where) that using a recursive stack is not efficient? – Andrew Simpson Nov 15 '13 at 14:33
  • 1
    The point of doing it recursively is so that if you delete an empty folder, the parent folder may now be empty and ready for deletion. There are times when I would worry about using recursion. A directory structure that is only 8 levels deep is not one of them. – Joel Rondeau Nov 15 '13 at 14:37
  • HI, Thanks again. Would not Directory.Delete("path","*", true) do that as well at the root level or..? – Andrew Simpson Nov 15 '13 at 14:41
  • 1
    Possibly, if done correctly. I would worry that I might try to delete a directory that has subdirectories but no files, when one of the subdirectories does have files in it. That's why I like the recursive way. I know each directory is empty when I delete it. Makes the code less complex. – Joel Rondeau Nov 15 '13 at 14:50
  • Hi, that is a fair enough comment. there have been a few suggestion shere that work (including yours) but out of preference only I have elected for the lambada solution. many thanks for your time – Andrew Simpson Nov 15 '13 at 15:01

3 Answers3

1

Here's a quick piece of code:

    static void Main(string[] args)
    {
        var baseDirectory = ".";

        DeleteEmptyDirectory(baseDirectory);
    }

    static bool DeleteEmptyDirectory(string directory)
    {
        var subDirs = Directory.GetDirectories(directory);
        var canDelete = true;
        if (subDirs.Any())
            foreach (var dir in subDirs)
                canDelete = DeleteEmptyDirectory(dir) && canDelete;
        if (canDelete && !Directory.GetFiles(directory).Any())
        {
            Directory.Delete(directory);
            return true;
        }
        else
            return false;
    }

This will delete all empty folders and leave anything with any files in it intact.

Regarding the comment you made about recursion... I wouldn't worry about it, unless you have crazy symlinks creating an infinite directory structure. ;)

MBender
  • 5,395
  • 1
  • 42
  • 69
1

A slightly different take, for comparison:

public static void DeleteEmptyFolders(string rootFolder)
{
    foreach (string subFolder in Directory.EnumerateDirectories(rootFolder))
        DeleteEmptyFolders(subFolder);

    DeleteFolderIfEmpty(rootFolder);
}

public static void DeleteFolderIfEmpty(string folder)
{
    if (!Directory.EnumerateFileSystemEntries(folder).Any())
        Directory.Delete(folder);
}

(I find this slightly more readable.)

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
1

Something like this?

private void KillFolders()
{
    DateTime to_date = DateTime.Now.AddDays(-1);
    List<string> paths = Directory.EnumerateDirectories(@"C:\MotionWise\Catalogue\" + Shared.ActiveMac, "*", SearchOption.TopDirectoryOnly)
        .Where(path =>
        {
            DateTime lastWriteTime = File.GetLastWriteTime(path);
            return lastWriteTime <= to_date;
        })
        .ToList();

    foreach (var path in paths))
    {
        cleanDirs(path);
    }
}

private static void cleanDirs(string startLocation)
{
    foreach (var directory in Directory.GetDirectories(startLocation))
    {
        cleanDirs(directory);
        if (Directory.GetFiles(directory).Length == 0 && Directory.GetDirectories(directory).Length == 0)
        {
            Directory.Delete(directory, false);
        }
    }
}

Note; this wont regard subdirs last writeTime. It will jsut take from the topDir where you have all the diff folders with dates older than a day and clean empty subdirs.

And if your goal is to simply clean empty folders in a target Dir the "cleanDirs" function woorks standalone..

SomeRandomName
  • 593
  • 1
  • 8
  • 23