ZetCode

C# list directory

last modified October 16, 2026

In this article we show how to list directory contents in C#. We list files and directories and filter the output based on the file name pattern, file extension, file size, modification date, or content.

Directory definition

A directory, also called a folder, is a location for storing files on a computer. In addition to files, a directory also stores other directories or links.

In C# we can use Directory or DirectoryInfo to work with directories. Directory is a static class that provides static methods for working with directories. An instance of DirectoryInfo provides information about a specific directory. Its methods return FileInfo and DirectoryInfo objects, which give us access to the size, dates, and attributes of the entries. The classes are available in the System.IO namespace.

The methods return either an enumerable collection (e.g. Directory.EnumerateFiles) or an array of values (e.g. Directory.GetFiles). When we use a method that returns an array, we must wait for the whole array to be returned, while with the enumerable collection, we can process the data right away. Working with enumerable collections is more efficient and takes less memory, especially for large directory trees.

The order in which the entries are returned is not guaranteed; it depends on the file system. Therefore, we sort the results in our examples.

Example directory

In the examples, we use the following data directory, which is located in the project directory.

data
├── 2025
│   ├── old
│   │   └── archive.pdf
│   ├── q1_data.csv
│   └── summary.txt
├── books
│   ├── marathon.txt
│   └── thermopylae.txt
├── images
│   ├── logo.png
│   └── photo.jpg
├── notes.md
├── report.txt
└── sales.csv

C# DirectoryInfo.EnumerateDirectories

The DirectoryInfo.EnumerateDirectories method returns an enumerable collection of directory information for the specified directory.

Program.cs
var dirInfo = new DirectoryInfo("data");

var options = new EnumerationOptions { RecurseSubdirectories = true };

foreach (var dir in dirInfo.EnumerateDirectories("*", options).OrderBy(d => d.FullName))
{
    Console.WriteLine(Path.GetRelativePath(".", dir.FullName));
}

In the example, we recursively find all directories in the chosen directory.

var options = new EnumerationOptions { RecurseSubdirectories = true };

The EnumerationOptions class controls the enumeration. With RecurseSubdirectories, the subdirectories are searched too.

Console.WriteLine(Path.GetRelativePath(".", dir.FullName));

The FullName property contains the absolute path. We print the path relative to the current directory.

$ dotnet run
data/2025
data/2025/old
data/books
data/images

C# Directory.GetDirectories and GetFiles

The Directory.GetDirectories and Directory.GetFiles methods return the names of subdirectories and files as string arrays. Without a search option, only the top level of the directory is listed.

Program.cs
string[] dirs = Directory.GetDirectories("data");
string[] files = Directory.GetFiles("data");

Console.WriteLine("Directories:");

foreach (var dir in dirs.Order())
{
    Console.WriteLine($"  {dir}");
}

Console.WriteLine("Files:");

foreach (var file in files.Order())
{
    Console.WriteLine($"  {file}");
}

The example lists the top-level subdirectories and files of the data directory. The returned names include the path that we passed to the methods.

$ dotnet run
Directories:
  data/2025
  data/books
  data/images
Files:
  data/notes.md
  data/report.txt
  data/sales.csv

C# Directory.EnumerateFiles search pattern

The second parameter of the EnumerateFiles, GetFiles, and similar methods is a search pattern. The * wildcard matches zero or more characters and the ? wildcard matches exactly one character. The SearchOption.AllDirectories option searches recursively.

Program.cs
var files = Directory.EnumerateFiles("data", "*.csv", SearchOption.AllDirectories);

foreach (var file in files.Order())
{
    Console.WriteLine(file);
}

The example recursively lists all CSV files.

$ dotnet run
data/2025/q1_data.csv
data/sales.csv

C# list files with multiple extensions

A search pattern can contain only one extension. To search for several extensions, we filter the files with LINQ.

Program.cs
var extensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
    ".csv", ".txt", ".pdf"
};

var files = Directory.EnumerateFiles("data", "*", SearchOption.AllDirectories)
    .Where(f => extensions.Contains(Path.GetExtension(f)))
    .Order()
    .ToList();

foreach (var file in files)
{
    Console.WriteLine(file);
}

Console.WriteLine($"{files.Count} files found");

The example recursively searches for CSV, TXT, and PDF files. The extensions are stored in a case-insensitive set, so that files such as REPORT.TXT are found too.

.ToList();

We materialize the query into a list. Otherwise, the directory tree would be searched twice: once in the loop and once when counting the files.

$ dotnet run
data/2025/old/archive.pdf
data/2025/q1_data.csv
data/2025/summary.txt
data/books/marathon.txt
data/books/thermopylae.txt
data/report.txt
data/sales.csv
7 files found

C# list files by file name

In the following example, we list files whose names contain a given word.

Program.cs
var files = from file in Directory.EnumerateFiles("data", "*", SearchOption.AllDirectories)
            where Path.GetFileName(file).Contains("data", StringComparison.OrdinalIgnoreCase)
            select file;

foreach (var file in files)
{
    Console.WriteLine(file);
}

The example searches recursively for files whose file name, the last part of the path, contains the word data. The directory name data in the path is not taken into account.

$ dotnet run
data/2025/q1_data.csv

C# list files by size

The DirectoryInfo.EnumerateFiles method returns FileInfo objects. The Length property of a FileInfo gives us the size of a file.

Program.cs
long limit = 10 * 1024;

var dirInfo = new DirectoryInfo("data");

var files = from fi in dirInfo.EnumerateFiles("*", SearchOption.AllDirectories)
            where fi.Length > limit
            orderby fi.Length descending
            select fi;

foreach (var fi in files)
{
    Console.WriteLine($"{fi.Name,-14} {fi.Length,8:N0} bytes");
}

The example finds all files larger than 10 KB and sorts them by size in descending order.

$ dotnet run
photo.jpg       480,000 bytes
archive.pdf     250,000 bytes
q1_data.csv      15,360 bytes
logo.png         12,000 bytes

C# list files by date

The FileInfo class has properties for the creation, last write, and last access times of a file.

Program.cs
var dateLimit = new DateTime(2025, 1, 1);

var dirInfo = new DirectoryInfo("data");

var files = from fi in dirInfo.EnumerateFiles("*", SearchOption.AllDirectories)
            where fi.LastWriteTime < dateLimit
            orderby fi.LastWriteTime
            select fi;

foreach (var fi in files)
{
    Console.WriteLine($"{fi.Name,-12} {fi.LastWriteTime:yyyy-MM-dd}");
}

In the example, we list all files that were last modified before 2025. We use the last write time, because the creation time is not reliably available on all file systems.

$ dotnet run
archive.pdf  2023-03-14
logo.png     2024-06-20
notes.md     2024-11-02

C# search file content

In the following example, we list the lines of text files that contain a given word.

Program.cs
var lines = from file in Directory.EnumerateFiles("data/books", "*.txt")
            from line in File.ReadLines(file)
            where line.Contains("Persian")
            orderby file
            select new { File = Path.GetFileName(file), Line = line };

foreach (var e in lines)
{
    Console.WriteLine($"{e.File}: {e.Line}");
}

The two from clauses go over all lines of all text files in the books directory. The File.ReadLines method reads the files lazily, line by line.

$ dotnet run
marathon.txt: The Battle of Marathon took place in 490 BC during the first Persian invasion
marathon.txt: and a Persian force commanded by Datis and Artaphernes.
thermopylae.txt: led by King Leonidas of Sparta, and the Persian Empire of Xerxes I over the
thermopylae.txt: course of three days, during the second Persian invasion of Greece.

C# directory size

In the following example, we determine the size of a directory.

Program.cs
var dirInfo = new DirectoryInfo("data");

long size = dirInfo.EnumerateFiles("*", SearchOption.AllDirectories)
    .Sum(fi => fi.Length);

Console.WriteLine($"The directory size: {size:N0} bytes");

We go over all files in the directory and its subdirectories and sum their sizes.

$ dotnet run
The directory size: 768,860 bytes

C# EnumerationOptions

The EnumerationOptions class provides more control than SearchOption. We can limit the depth of the recursion, set the case sensitivity of the search pattern, or skip entries with certain attributes. By default, it also skips files and directories that we do not have permission to access; with SearchOption.AllDirectories, such an entry throws an UnauthorizedAccessException and stops the whole enumeration.

Program.cs
var options = new EnumerationOptions
{
    RecurseSubdirectories = true,
    MaxRecursionDepth = 1,
    MatchCasing = MatchCasing.CaseInsensitive,
    IgnoreInaccessible = true
};

foreach (var file in Directory.EnumerateFiles("data", "*.TXT", options).Order())
{
    Console.WriteLine(file);
}

We search for text files with a case-insensitive pattern. The search goes only one level deep; the files in data/2025/old would not be found.

$ dotnet run
data/2025/summary.txt
data/books/marathon.txt
data/books/thermopylae.txt
data/report.txt

Source

How to enumerate directories and files

In this article we have shown how to list directories in C#.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all C# tutorials.