Question

Delete Directory Contents While Keeping the Root Folder in C#

csharp.net

Question

Using C#, how can I delete every file and subdirectory inside a directory while keeping the root directory itself intact?

Short Answer

You will learn how C# represents directories and files, how to delete a directory's immediate contents safely, and why deleting the root directory is different from clearing it. You will also see practical patterns for validation, error handling, and recursive deletion.

Concept

A directory has two separate parts:

  • The root directory: the folder whose path you start with.
  • Its contents: files and nested subdirectories inside that folder.

To keep the root directory, delete its contents individually rather than calling Directory.Delete on the root path.

In C#, DirectoryInfo provides object-oriented methods for inspecting a folder:

  • GetFiles() returns files directly inside the directory.
  • GetDirectories() returns subdirectories directly inside it.
  • FileInfo.Delete() deletes one file.
  • DirectoryInfo.Delete(true) deletes a directory and everything beneath it recursively.

This distinction matters in applications that use a permanent working folder, such as a cache, upload staging area, export location, or temporary report directory. The application may expect that root folder to remain available after cleanup.

Mental Model

Think of the root directory as a cupboard and its contents as papers and smaller boxes inside it.

  • Deleting a file removes one paper.
  • Deleting a subdirectory recursively removes a smaller box and everything in it.
  • The cupboard stays in place because you never delete the cupboard itself.

Calling Directory.Delete(rootPath, true) is different: it removes the entire cupboard, not just what is inside it.

Take Quiz

Syntax and Examples

Use DirectoryInfo to get the root folder's direct children, then delete each child.

using System;
using System.IO;

string rootPath = @"C:\Temp\Work";
DirectoryInfo root = new DirectoryInfo(rootPath);

if (!root.Exists)
{
    throw new DirectoryNotFoundException($"Directory not found: {rootPath}");
}

foreach (FileInfo file in root.GetFiles())
{
    file.Delete();
}

foreach (DirectoryInfo directory in root.GetDirectories())
{
    directory.Delete(recursive: true);
}

root.GetFiles() gets files directly in C:\Temp\Work, and file.Delete() removes them.

root.GetDirectories() gets only the direct child folders. Passing recursive: true to directory.Delete deletes each child folder along with all files and folders nested inside it.

The root variable is never deleted, so C:\Temp\Work remains after the cleanup.

Step by Step Execution

Consider this folder structure:

C:\Temp\Work
├── notes.txt
├── output.csv
└── Archive
    ├── old.txt
    └── Images
        └── logo.png

Code:

DirectoryInfo root = new DirectoryInfo(@"C:\Temp\Work");

foreach (FileInfo file in root.GetFiles())
{
    file.Delete();
}

foreach (DirectoryInfo directory in root.GetDirectories())
{
    directory.Delete(true);
}

Execution:

  1. new DirectoryInfo(...) creates an object representing C:\Temp\Work. It does not delete or create anything yet.
  2. GetFiles() returns notes.txt and output.csv.
  3. The first loop deletes both files.
  4. GetDirectories() returns Archive.
  5. Archive.Delete(true) deletes Archive, old.txt, Images, and logo.png.
  6. C:\Temp\Work still exists, but it is now empty.

Real World Use Cases

Common reasons to clear a folder while retaining it include:

  • Application caches: remove cached thumbnails or downloaded data before rebuilding them.
  • Upload staging folders: clear files from a previous processing job before accepting a new upload.
  • Report exports: remove old CSV or PDF exports before generating the latest set.
  • Build or test artifacts: clean generated output before a build or integration test.
  • Scheduled maintenance: clear a known temporary workspace without changing its configured path.

In all cases, use a path controlled by your application. Avoid deleting a path supplied directly by an untrusted user.

Take Quiz

Real Codebase Usage

Production code usually wraps cleanup in a method that validates the path and handles expected failures.

using System;
using System.IO;

public static class DirectoryCleaner
{
    public static void ClearContents(string rootPath)
    {
        if (string.IsNullOrWhiteSpace(rootPath))
        {
            throw new ArgumentException("A directory path is required.", nameof(rootPath));
        }

        DirectoryInfo root = new DirectoryInfo(rootPath);

        if (!root.Exists)
        {
            return; // Nothing to clean.
        }

        foreach (FileInfo file in root.GetFiles())
        {
            file.Delete();
        }

        foreach (DirectoryInfo directory in root.GetDirectories())
        {
            directory.Delete(recursive: true);
        }
    }
}

Useful real-project practices:

  • Use a guard clause to reject missing or invalid input early.
  • Treat a missing cleanup directory as a no-op when that fits the application.
  • Log UnauthorizedAccessException or IOException if cleanup is best-effort rather than critical.
  • Ensure the path is an intended application workspace before deleting anything.
  • Do not delete files that are still open by your own process; dispose streams first with using.

Common Mistakes

Deleting the root directory accidentally

This deletes the root folder too:

Directory.Delete(rootPath, recursive: true);

Use this only when you explicitly want to remove rootPath. To retain it, enumerate and delete its children instead.

Forgetting recursive deletion for child folders

This works only if subdirectory is empty:

subdirectory.Delete();

Use recursive deletion for a child directory that may contain files:

subdirectory.Delete(recursive: true);

Assuming GetFiles() includes nested files

foreach (FileInfo file in root.GetFiles())
{
    file.Delete();
}

This deletes only files directly in root; it does not delete files inside child folders. Delete the child folders recursively as well.

Ignoring locked files and permissions

A file can fail to delete because another process is using it, or because the application lacks permission. File operations can throw exceptions such as:

  • UnauthorizedAccessException
  • IOException

Handle or report these errors according to your application's requirements. Do not silently ignore failures when complete cleanup is required.

Using a dangerous path

Never run recursive deletion against a path unless you have verified it is the intended workspace. A typo in a configured path can delete important data.

Comparisons

ApproachKeeps the root directory?Deletes nested contents?Best use
Loop through files and child directoriesYesYes, when child directories use Delete(true)Clear an existing workspace
Directory.Delete(rootPath, true)NoYesRemove the root directory completely
Delete root, then Directory.CreateDirectory(rootPath)Eventually yesYesSometimes used for a full reset, but has a period where the folder does not exist
Delete only files with GetFiles()YesNoClear files only and preserve subfolders

DirectoryInfo and the static Directory class can both perform directory work. DirectoryInfo is convenient here because GetFiles() returns FileInfo objects and GetDirectories() returns DirectoryInfo objects, each with its own Delete method.

Take Quiz

Cheat Sheet

using System.IO;

DirectoryInfo root = new DirectoryInfo(rootPath);

if (root.Exists)
{
    foreach (FileInfo file in root.GetFiles())
    {
        file.Delete();
    }

    foreach (DirectoryInfo directory in root.GetDirectories())
    {
        directory.Delete(recursive: true);
    }
}
  • GetFiles() returns files directly inside a directory.
  • GetDirectories() returns direct child directories.
  • file.Delete() deletes one file.
  • directory.Delete(true) deletes a directory and all descendants.
  • Directory.Delete(rootPath, true) also deletes the root itself.
  • Check Exists before cleanup when a missing directory is acceptable.
  • Expect permission and file-lock failures in real environments.

FAQ

How do I delete all files in a directory but not its subfolders in C#?

Use root.GetFiles() and call Delete() for each returned file. Do not loop through root.GetDirectories().

Does GetFiles() search subdirectories automatically?

No. GetFiles() without a search option returns only files directly in the specified directory.

Does DirectoryInfo.Delete(true) delete the directory itself?

Yes. When called on a child directory, it deletes that child and everything below it. When called on the root directory, it deletes the root too.

What happens if the directory does not exist?

new DirectoryInfo(path) does not fail merely because the directory is missing, but accessing its contents can fail. Check root.Exists first if the directory may be absent.

Why does file deletion throw an IOException?

Common causes include a file being open by another process, a temporary system lock, or an I/O problem. Close streams and retry or report the error as appropriate.

Can I clear a directory with Directory.Delete and recreate it?

Yes, but it briefly removes the root directory. Deleting children is usually preferable when other code expects the root to remain present.

Is recursive deletion safe?

It is safe only when the target path has been carefully validated. Recursive deletion can remove a large amount of data quickly.

Take Quiz

Mini Project

Description

Build a small console cleanup utility for a temporary workspace. It ensures the workspace exists, removes every file and nested folder inside it, and leaves the workspace ready for the next task.

Goal

Create a C# console program that clears a chosen workspace directory without deleting the workspace itself.

Requirements

Ensure the workspace directory exists before cleanup.

Delete every file directly inside the workspace.

Delete every subdirectory and all of its contents.

Print a confirmation that the root workspace still exists.

Use a clearly named workspace path that can be changed safely.

Take Quiz

Keep learning

Related questions

View more