Using C#, how can I delete all files and folders from a directory, but still keep the root directory?
-
https://stackoverflow.com/a/74443147/7186739 – Billu Nov 15 '22 at 09:17
32 Answers
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()
.

- 24,203
- 9
- 60
- 84

- 27,557
- 22
- 88
- 134
-
4Calling 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
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();

- 182,639
- 35
- 285
- 343
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();
}
}

- 7,373
- 6
- 36
- 49

- 841
- 6
- 2
The simplest way:
Directory.Delete(path,true);
Directory.CreateDirectory(path);
Be aware that this may wipe out some permissions on the folder.

- 30,033
- 48
- 152
- 225

- 912
- 6
- 4
-
This might not work for special folders where you need proper permissions. – dequid May 12 '23 at 07:49
new System.IO.DirectoryInfo(@"C:\Temp").Delete(true);
//Or
System.IO.Directory.Delete(@"C:\Temp", true);

- 8,432
- 8
- 46
- 54
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);

- 8,648
- 5
- 43
- 56
-
Points for handling exceptions. I don't want to delete files if they're open for writing somewhere else. – Phil Cairns Jun 16 '22 at 01:13
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);
}
}
}

- 30,738
- 21
- 105
- 131

- 5,288
- 2
- 45
- 60
I used
Directory.GetFiles(picturePath).ToList().ForEach(File.Delete);
for delete the old picture and I don't need any object in this folder

- 4,411
- 2
- 36
- 74

- 619
- 7
- 12
System.IO.Directory.Delete(installPath, true);
System.IO.Directory.CreateDirectory(installPath);

- 18,332
- 38
- 160
- 245
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;
}

- 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
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);

- 1,151
- 1
- 16
- 24
string directoryPath = "C:\Temp";
Directory.GetFiles(directoryPath).ToList().ForEach(File.Delete);
Directory.GetDirectories(directoryPath).ToList().ForEach(Directory.Delete);

- 1,725
- 1
- 13
- 8
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);
}
}
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;

- 455
- 8
- 16

- 97
- 1
- 1
-
4This also deletes the root directory, which isn't what the question asks. – Arkane Oct 13 '21 at 15:42
-
1this can be problem if the root directory has specific ACL's or other NTFS configuration. – Moshe L Jun 16 '23 at 09:56
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);

- 30,738
- 21
- 105
- 131

- 101
- 1
- 3
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();
}
}

- 23,309
- 10
- 44
- 76
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);
}
}

- 30,738
- 21
- 105
- 131

- 2,179
- 1
- 23
- 22
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();
}
}

- 551
- 4
- 3
use DirectoryInfo's GetDirectories method.
foreach (DirectoryInfo subDir in new DirectoryInfo(targetDir).GetDirectories())
subDir.Delete(true);

- 2,474
- 2
- 35
- 53
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.

- 25,467
- 18
- 120
- 187

- 113
- 1
- 5
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);
}
}

- 7,373
- 6
- 36
- 49

- 21
- 2
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]);
}

- 325
- 1
- 4
- 12
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();
});

- 43
- 6
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);
}

- 7,373
- 6
- 36
- 49

- 11
- 1
DirectoryInfo Folder = new DirectoryInfo(Server.MapPath(path));
if (Folder .Exists)
{
foreach (FileInfo fl in Folder .GetFiles())
{
fl.Delete();
}
Folder .Delete();
}

- 12,738
- 8
- 75
- 95

- 1
- 1
using System.IO;
string[] filePaths = Directory.GetFiles(@"c:\MyDir\");
foreach (string filePath in filePaths)
File.Delete(filePath);

- 4,687
- 6
- 32
- 49

- 11
- 4
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);
}
}

- 7,373
- 6
- 36
- 49

- 4,595
- 2
- 36
- 37
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();
}
}

- 2,733
- 26
- 47
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
}

- 19
- 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();
}
}
}

- 5,278
- 43
- 65
- 115

- 21
- 2
The only thing you should do is to set optional recursive parameter
to True
.
Directory.Delete("C:\MyDummyDirectory", True)
Thanks to .NET. :)

- 115
- 1
- 1
- 6
IO.Directory.Delete(HttpContext.Current.Server.MapPath(path), True)
You don't need more than that

- 6,175
- 3
- 37
- 61

- 1
- 1