851

Using C#, how can I delete all files and folders from a directory, but still keep the root directory?

Carlos Muñoz
  • 17,397
  • 7
  • 55
  • 80
JL.
  • 78,954
  • 126
  • 311
  • 459

32 Answers32

1102
System.IO.DirectoryInfo di = new DirectoryInfo("YourPath");

foreach (FileInfo file in di.GetFiles())
{
    file.Delete(); 
}
foreach (DirectoryInfo dir in di.GetDirectories())
{
    dir.Delete(true); 
}

If your directory may have many files, EnumerateFiles() is more efficient than GetFiles(), because when you use EnumerateFiles() you can start enumerating it before the whole collection is returned, as opposed to GetFiles() where you need to load the entire collection in memory before begin to enumerate it. See this quote here:

Therefore, when you are working with many files and directories, EnumerateFiles() can be more efficient.

The same applies to EnumerateDirectories() and GetDirectories(). So the code would be:

foreach (FileInfo file in di.EnumerateFiles())
{
    file.Delete(); 
}
foreach (DirectoryInfo dir in di.EnumerateDirectories())
{
    dir.Delete(true); 
}

For the purpose of this question, there is really no reason to use GetFiles() and GetDirectories().

Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
gsharp
  • 27,557
  • 22
  • 88
  • 134
  • 4
    Calling file.Delete() and then dir.Delete(true) is redundant since dir.Delete(true) recursively deletes all files and folders in the specified directory. Simply calling di.Delete(true) avoids needing two foreach loops: https://learn.microsoft.com/en-us/dotnet/api/system.io.directoryinfo.delete?view=net-5.0#System_IO_DirectoryInfo_Delete_System_Boolean_ – NotoriousPyro Jun 30 '21 at 16:06
  • 5
    @NotoriousPyro the user wants the root folder to be kept, that's why two foreach – gsharp Jul 01 '21 at 17:19
205

Yes, that's the correct way to do it. If you're looking to give yourself a "Clean" (or, as I'd prefer to call it, "Empty" function), you can create an extension method.

public static void Empty(this System.IO.DirectoryInfo directory)
{
    foreach(System.IO.FileInfo file in directory.GetFiles()) file.Delete();
    foreach(System.IO.DirectoryInfo subDirectory in directory.GetDirectories()) subDirectory.Delete(true);
}

This will then allow you to do something like..

System.IO.DirectoryInfo directory = new System.IO.DirectoryInfo(@"C:\...");

directory.Empty();
Adam Robinson
  • 182,639
  • 35
  • 285
  • 343
84

The following code will clear the folder recursively:

private void clearFolder(string FolderName)
{
    DirectoryInfo dir = new DirectoryInfo(FolderName);

    foreach(FileInfo fi in dir.GetFiles())
    {
        fi.Delete();
    }

    foreach (DirectoryInfo di in dir.GetDirectories())
    {
        clearFolder(di.FullName);
        di.Delete();
    }
}
Tshilidzi Mudau
  • 7,373
  • 6
  • 36
  • 49
hiteshbiblog
  • 841
  • 6
  • 2
78

The simplest way:

Directory.Delete(path,true);  
Directory.CreateDirectory(path);

Be aware that this may wipe out some permissions on the folder.

Brian Webster
  • 30,033
  • 48
  • 152
  • 225
Igor Mukhachev
  • 912
  • 6
  • 4
46
 new System.IO.DirectoryInfo(@"C:\Temp").Delete(true);

 //Or

 System.IO.Directory.Delete(@"C:\Temp", true);
Thulasiram
  • 8,432
  • 8
  • 46
  • 54
41
private void ClearFolder(string FolderName)
{
    DirectoryInfo dir = new DirectoryInfo(FolderName);

    foreach(FileInfo fi in dir.GetFiles())
    {
        try
        {
            fi.Delete();
        }
        catch(Exception) { } // Ignore all exceptions
    }

    foreach(DirectoryInfo di in dir.GetDirectories())
    {
        ClearFolder(di.FullName);
        try
        {
            di.Delete();
        }
        catch(Exception) { } // Ignore all exceptions
    }
}

If you know there are no sub-folders, something like this may be the easiest:

    Array.ForEach(Directory.GetFiles(folderName), File.Delete);
zumalifeguard
  • 8,648
  • 5
  • 43
  • 56
40

We can also show love for LINQ:

using System.IO;
using System.Linq;
…
var directory = Directory.GetParent(TestContext.TestDir);

directory.EnumerateFiles()
    .ToList().ForEach(f => f.Delete());

directory.EnumerateDirectories()
    .ToList().ForEach(d => d.Delete(true));

Note that my solution here is not performant, because I am using Get*().ToList().ForEach(...) which generates the same IEnumerable twice. I use an extension method to avoid this issue:

using System.IO;
using System.Linq;
…
var directory = Directory.GetParent(TestContext.TestDir);

directory.EnumerateFiles()
    .ForEachInEnumerable(f => f.Delete());

directory.EnumerateDirectories()
    .ForEachInEnumerable(d => d.Delete(true));

This is the extension method:

/// <summary>
/// Extensions for <see cref="System.Collections.Generic.IEnumerable"/>.
/// </summary>
public static class IEnumerableOfTExtensions
{
    /// <summary>
    /// Performs the <see cref="System.Action"/>
    /// on each item in the enumerable object.
    /// </summary>
    /// <typeparam name="TEnumerable">The type of the enumerable.</typeparam>
    /// <param name="enumerable">The enumerable.</param>
    /// <param name="action">The action.</param>
    /// <remarks>
    /// “I am philosophically opposed to providing such a method, for two reasons.
    /// …The first reason is that doing so violates the functional programming principles
    /// that all the other sequence operators are based upon. Clearly the sole purpose of a call
    /// to this method is to cause side effects.”
    /// —Eric Lippert, “foreach” vs “ForEach” [http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx]
    /// </remarks>
    public static void ForEachInEnumerable<TEnumerable>(this IEnumerable<TEnumerable> enumerable, Action<TEnumerable> action)
    {
        foreach (var item in enumerable)
        {
            action(item);
        }
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
rasx
  • 5,288
  • 2
  • 45
  • 60
22

I used

Directory.GetFiles(picturePath).ToList().ForEach(File.Delete);

for delete the old picture and I don't need any object in this folder

clamchoda
  • 4,411
  • 2
  • 36
  • 74
15
System.IO.Directory.Delete(installPath, true);
System.IO.Directory.CreateDirectory(installPath);
JustBeingHelpful
  • 18,332
  • 38
  • 160
  • 245
9

Here is the tool I ended with after reading all posts. It does

  • Deletes all that can be deleted
  • Returns false if some files remain in folder

It deals with

  • Readonly files
  • Deletion delay
  • Locked files

It doesn't use Directory.Delete because the process is aborted on exception.

    /// <summary>
    /// Attempt to empty the folder. Return false if it fails (locked files...).
    /// </summary>
    /// <param name="pathName"></param>
    /// <returns>true on success</returns>
    public static bool EmptyFolder(string pathName)
    {
        bool errors = false;
        DirectoryInfo dir = new DirectoryInfo(pathName);

        foreach (FileInfo fi in dir.EnumerateFiles())
        {
            try
            {
                fi.IsReadOnly = false;
                fi.Delete();

                //Wait for the item to disapear (avoid 'dir not empty' error).
                while (fi.Exists)
                {
                    System.Threading.Thread.Sleep(10);
                    fi.Refresh();
                }
            }
            catch (IOException e)
            {
                Debug.WriteLine(e.Message);
                errors = true;
            }
        }

        foreach (DirectoryInfo di in dir.EnumerateDirectories())
        {
            try
            {
                EmptyFolder(di.FullName);
                di.Delete();

                //Wait for the item to disapear (avoid 'dir not empty' error).
                while (di.Exists)
                {
                    System.Threading.Thread.Sleep(10);
                    di.Refresh();
                }
            }
            catch (IOException e)
            {
                Debug.WriteLine(e.Message);
                errors = true;
            }
        }

        return !errors;
    }
Eric Bole-Feysot
  • 13,949
  • 7
  • 47
  • 53
  • Well, today I learnt that a readonly file cannot be deleted programatically. How does your code deal with locked files, though? Doesn't it just skip them? – Arkane Oct 13 '21 at 15:53
  • @Arkane, I just remove the readonly flag, delete the file and wait for it to disappear from the folder. If it's not, I set an error flag. – Eric Bole-Feysot Oct 15 '21 at 13:01
  • For locked files, they can't be deleted, so they remain. I skip them and return false to state that some files are still there. – Eric Bole-Feysot Feb 23 '22 at 10:40
8

Every method that I tried, they have failed at some point with System.IO errors. The following method works for sure, even if the folder is empty or not, read-only or not, etc.

ProcessStartInfo Info = new ProcessStartInfo();  
Info.Arguments = "/C rd /s /q \"C:\\MyFolder"";  
Info.WindowStyle = ProcessWindowStyle.Hidden;  
Info.CreateNoWindow = true;  
Info.FileName = "cmd.exe";  
Process.Start(Info); 
Alexandru Dicu
  • 1,151
  • 1
  • 16
  • 24
7
string directoryPath = "C:\Temp";
Directory.GetFiles(directoryPath).ToList().ForEach(File.Delete);
Directory.GetDirectories(directoryPath).ToList().ForEach(Directory.Delete);
AVH
  • 1,725
  • 1
  • 13
  • 8
7

Using just static methods with File and Directory instead of FileInfo and DirectoryInfo will perform faster. (see accepted answer at What is the difference between File and FileInfo in C#?). Answer shown as utility method.

public static void Empty(string directory)
{
    foreach(string fileToDelete in System.IO.Directory.GetFiles(directory))
    {
        System.IO.File.Delete(fileToDelete);
    }
    foreach(string subDirectoryToDeleteToDelete in System.IO.Directory.GetDirectories(directory))
    {
        System.IO.Directory.Delete(subDirectoryToDeleteToDelete, true);
    }
}
Community
  • 1
  • 1
Kriil
  • 560
  • 7
  • 15
7

I know this is an ancient question but this is the (perhaps new) correct answer:

new DirectoryInfo(folder).Delete(true);
Directory.CreateDirectory(folder);

Deletes all recursive and then recreates the folder.

PS - Must have reference using System.IO;

Rui Caramalho
  • 455
  • 8
  • 16
Piet du Preez
  • 97
  • 1
  • 1
6

The following code will clean the directory, but leave the root directory there (recursive).

Action<string> DelPath = null;
DelPath = p =>
{
    Directory.EnumerateFiles(p).ToList().ForEach(File.Delete);
    Directory.EnumerateDirectories(p).ToList().ForEach(DelPath);
    Directory.EnumerateDirectories(p).ToList().ForEach(Directory.Delete);
};
DelPath(path);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
hofi
  • 101
  • 1
  • 3
6
private void ClearFolder(string FolderName)
{
    DirectoryInfo dir = new DirectoryInfo(FolderName);

    foreach (FileInfo fi in dir.GetFiles())
    {
        fi.IsReadOnly = false;
        fi.Delete();
    }

    foreach (DirectoryInfo di in dir.GetDirectories())
    {
        ClearFolder(di.FullName);
        di.Delete();
    }
}
Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
4

In Windows 7, if you have just created it manually with Windows Explorer, the directory structure is similar to this one:

C:
  \AAA
    \BBB
      \CCC
        \DDD

And running the code suggested in the original question to clean the directory C:\AAA, the line di.Delete(true) always fails with IOException "The directory is not empty" when trying to delete BBB. It is probably because of some kind of delays/caching in Windows Explorer.

The following code works reliably for me:

static void Main(string[] args)
{
    DirectoryInfo di = new DirectoryInfo(@"c:\aaa");
    CleanDirectory(di);
}

private static void CleanDirectory(DirectoryInfo di)
{
    if (di == null)
        return;

    foreach (FileSystemInfo fsEntry in di.GetFileSystemInfos())
    {
        CleanDirectory(fsEntry as DirectoryInfo);
        fsEntry.Delete();
    }
    WaitForDirectoryToBecomeEmpty(di);
}

private static void WaitForDirectoryToBecomeEmpty(DirectoryInfo di)
{
    for (int i = 0; i < 5; i++)
    {
        if (di.GetFileSystemInfos().Length == 0)
            return;
        Console.WriteLine(di.FullName + i);
        Thread.Sleep(50 * i);
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
farfareast
  • 2,179
  • 1
  • 23
  • 22
4

This version does not use recursive calls, and solves the readonly problem.

public static void EmptyDirectory(string directory)
{
    // First delete all the files, making sure they are not readonly
    var stackA = new Stack<DirectoryInfo>();
    stackA.Push(new DirectoryInfo(directory));

    var stackB = new Stack<DirectoryInfo>();
    while (stackA.Any())
    {
        var dir = stackA.Pop();
        foreach (var file in dir.GetFiles())
        {
            file.IsReadOnly = false;
            file.Delete();
        }
        foreach (var subDir in dir.GetDirectories())
        {
            stackA.Push(subDir);
            stackB.Push(subDir);
        }
    }

    // Then delete the sub directories depth first
    while (stackB.Any())
    {
        stackB.Pop().Delete();
    }
}
Jeppe Andreasen
  • 551
  • 4
  • 3
2

use DirectoryInfo's GetDirectories method.

foreach (DirectoryInfo subDir in new DirectoryInfo(targetDir).GetDirectories())
                    subDir.Delete(true);
Mr_Hmp
  • 2,474
  • 2
  • 35
  • 53
2

The following example shows how you can do that. It first creates some directories and a file and then removes them via Directory.Delete(topPath, true);:

    static void Main(string[] args)
    {
        string topPath = @"C:\NewDirectory";
        string subPath = @"C:\NewDirectory\NewSubDirectory";

        try
        {
            Directory.CreateDirectory(subPath);

            using (StreamWriter writer = File.CreateText(subPath + @"\example.txt"))
            {
                writer.WriteLine("content added");
            }

            Directory.Delete(topPath, true);

            bool directoryExists = Directory.Exists(topPath);

            Console.WriteLine("top-level directory exists: " + directoryExists);
        }
        catch (Exception e)
        {
            Console.WriteLine("The process failed: {0}", e.Message);
        }
    }

It is taken from https://msdn.microsoft.com/en-us/library/fxeahc5f(v=vs.110).aspx.

Matt
  • 25,467
  • 18
  • 120
  • 187
Salma Tofaily
  • 113
  • 1
  • 5
1

To delete the folder, this is code using Text box and a button using System.IO; :

private void Deletebt_Click(object sender, EventArgs e)
{
    System.IO.DirectoryInfo myDirInfo = new DirectoryInfo(@"" + delete.Text);

    foreach (FileInfo file in myDirInfo.GetFiles())
    {
       file.Delete();
    }
    foreach (DirectoryInfo dir in myDirInfo.GetDirectories())
    {
       dir.Delete(true);
    }
}
Tshilidzi Mudau
  • 7,373
  • 6
  • 36
  • 49
1

It's not the best way to deal with the issue above. But it's an alternative one...

while (Directory.GetDirectories(dirpath).Length > 0)
 {
       //Delete all files in directory
       while (Directory.GetFiles(Directory.GetDirectories(dirpath)[0]).Length > 0)
       {
            File.Delete(Directory.GetFiles(dirpath)[0]);
       }
       Directory.Delete(Directory.GetDirectories(dirpath)[0]);
 }
dsmyrnaios
  • 325
  • 1
  • 4
  • 12
1

DirectoryInfo.GetFileSystemInfos returns both files and directories :-

new DirectoryInfo(targetDir).GetFileSystemInfos().ToList().ForEach(x => x.Delete());

or if you want to recursive delete :-

        new DirectoryInfo(targetDir).GetFileSystemInfos().ToList().ForEach(x =>
        {
            if (x is DirectoryInfo di)
                di.Delete(true);
            else
                x.Delete();
        });
triksma
  • 43
  • 6
0
 foreach (string file in System.IO.Directory.GetFiles(path))
 {
    System.IO.File.Delete(file);
 }

 foreach (string subDirectory in System.IO.Directory.GetDirectories(path))
 {
     System.IO.Directory.Delete(subDirectory,true); 
 } 
Tshilidzi Mudau
  • 7,373
  • 6
  • 36
  • 49
Manish Y
  • 11
  • 1
0
DirectoryInfo Folder = new DirectoryInfo(Server.MapPath(path)); 
if (Folder .Exists)
{
    foreach (FileInfo fl in Folder .GetFiles())
    {
        fl.Delete();
    }

    Folder .Delete();
}
Entreco
  • 12,738
  • 8
  • 75
  • 95
0
using System.IO;

string[] filePaths = Directory.GetFiles(@"c:\MyDir\");

foreach (string filePath in filePaths)

File.Delete(filePath);
Julian E.
  • 4,687
  • 6
  • 32
  • 49
SynsMasTer
  • 11
  • 4
0

Call from main

static void Main(string[] args)
{ 
   string Filepathe =<Your path>
   DeleteDirectory(System.IO.Directory.GetParent(Filepathe).FullName);              
}

Add this method

public static void DeleteDirectory(string path)
{
    if (Directory.Exists(path))
    {
        //Delete all files from the Directory
        foreach (string file in Directory.GetFiles(path))
        {
            File.Delete(file);
        }
        //Delete all child Directories
        foreach (string directory in Directory.GetDirectories(path))
        {
             DeleteDirectory(directory);
        }
        //Delete a Directory
        Directory.Delete(path);
    }
 }
Tshilidzi Mudau
  • 7,373
  • 6
  • 36
  • 49
sansalk
  • 4,595
  • 2
  • 36
  • 37
0

In my Case

var PhotoFile = _context.Records.Where(x => id_or_ids.Contains(x.Id)).Select(x => x.Photo).ToList();

            System.IO.DirectoryInfo di = new DirectoryInfo("wwwroot/uploads");

            foreach (FileInfo file in di.GetFiles())
            {
                if (PhotoFile.IndexOf(file.Name) != -1)
                {
                    file.Delete();
                }
            }
Billu
  • 2,733
  • 26
  • 47
-1
private void ClearDirectory(string path)
{
    if (Directory.Exists(path))//if folder exists
    {
        Directory.Delete(path, true);//recursive delete (all subdirs, files)
    }
    Directory.CreateDirectory(path);//creates empty directory
}
dadziu
  • 19
  • 1
-1

this will show how we delete the folder and check for it we use Text box

using System.IO;
namespace delete_the_folder
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Deletebt_Click(object sender, EventArgs e)
    {
        //the  first you should write the folder place
        if (Pathfolder.Text=="")
        {
            MessageBox.Show("ples write the path of the folder");
            Pathfolder.Select();
            //return;
        }

        FileAttributes attr = File.GetAttributes(@Pathfolder.Text);

        if (attr.HasFlag(FileAttributes.Directory))
            MessageBox.Show("Its a directory");
        else
            MessageBox.Show("Its a file");

        string path = Pathfolder.Text;
        FileInfo myfileinf = new FileInfo(path);
        myfileinf.Delete();

    }


}

}
Robert
  • 5,278
  • 43
  • 65
  • 115
-3

The only thing you should do is to set optional recursive parameter to True.

Directory.Delete("C:\MyDummyDirectory", True)

Thanks to .NET. :)

LysanderM
  • 115
  • 1
  • 1
  • 6
-4
IO.Directory.Delete(HttpContext.Current.Server.MapPath(path), True)

You don't need more than that

Anri
  • 6,175
  • 3
  • 37
  • 61