Search code examples
c#delete-filesystem.io.filesystem.io.directory

How to skip files while deleting


I'm building an console application to delete files and folders from appdata/local/temp. I have referred multiple sites & pages in SO. But unfortunately couldn't get much.

What I have done so far:

Method 1: Directory.Delete(folderPath, true);

Method 2: Recursive Delete

public static void RecursiveDelete(DirectoryInfo baseDir)
{
    if (!baseDir.Exists)
        return;

    foreach (var dir in baseDir.EnumerateDirectories())
    {
        RecursiveDelete(dir);
    }
    baseDir.Delete(true);
}

Method 3: try-catch

foreach (DirectoryInfo subDir in directoryInfo.GetDirectories())
{
    try
    {
        subDir.Delete();
    }
    catch (Exception ex)
    {
        continue;
    }
}

foreach (FileInfo file in directoryInfo.GetFiles())
{
    try
    {
        file.Delete();
    }
    catch (Exception ex)
    {
        continue;
    }
}

These methods are fine but there is a popup always coming up saying - Folder access denied or File in use.

What I want?

I want to click on the checkbox that says - do this for all current items and click skip.

I'm unable to figure out how to implement this. It would be really helpful if someone can help me with this. Thanks in advance.


Solution

  • First of all, you shouldn't try to just delete folders that may be in use by other applications. This will break the applications and can easily lead to lost data.

    If you just try to delete the entire %TEMP% folder on Windows, you'll lose all the pending files you had in VS Code or Sublime but didn't bother saving in a specific folder.


    Ignoring inaccessible files and folders is possible out of the box in .NET Core, which include .NET 5 and later versions.

    Recursive searching was always possible by passing the SearchOption.AllDirectories parameter to EnumerateFiles:

    var allFiles=baseDir.EnumerateFiles("*",SearchOption.AllDirectories);
    

    .NET Core added an overload that accepts an EnumerationOptions object which allows ignoring inaccessible folders and objecgts:

    var options=new EnumerationOptions { 
        RecuresSubdirectories=true, 
        IgnoreInaccessible=true
    };
    var allFiles=baseDir.EnumerateFiles("*",options);
    

    This won't exclude files that are in use. You still need to use a try/catch block but you don't have to worry about permissions :

    foreach(var file in allFiles)
    {
        try
        {
            file.Delete();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Can't delete {file.FullPath}");
        }
    }
    

    To avoid deleting temporary files that are still needed, you can try deleting only those that haven't been modified in a while using the LastAccessTime property :

    var oldFiles=baseDir.EnumerateFiles("*",options)
                 .Where(file=>file.LastAccessTime=DateTime.Now.AddDays(-7));