C#
directory paths
path comparison
programming
.NET

How can I compare directory paths in C?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Comparing directory paths in C# is harder than comparing two raw strings. Paths may differ by case, trailing separators, relative segments, or platform rules. A reliable comparison starts by normalizing both paths and then using the correct string comparer for the target operating system.

Normalize Before Comparing

Two paths can point to the same directory even when the text is different. For example, C:\logs\app, C:\logs\app\, and C:\logs\temp\..\app all refer to the same location on Windows.

The first step is to convert each path to a canonical string:

csharp
1using System;
2using System.IO;
3
4public static class PathComparison
5{
6    public static string NormalizeDirectoryPath(string path)
7    {
8        if (string.IsNullOrWhiteSpace(path))
9        {
10            throw new ArgumentException("Path must not be empty.", nameof(path));
11        }
12
13        var fullPath = Path.GetFullPath(path);
14        return fullPath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
15    }
16
17    public static bool AreSameDirectory(string left, string right, StringComparer comparer)
18    {
19        var normalizedLeft = NormalizeDirectoryPath(left);
20        var normalizedRight = NormalizeDirectoryPath(right);
21        return comparer.Equals(normalizedLeft, normalizedRight);
22    }
23}
24
25public class Program
26{
27    public static void Main()
28    {
29        var result = PathComparison.AreSameDirectory(
30            @"C:\logs\app\",
31            @"C:\logs\temp\..\app",
32            StringComparer.OrdinalIgnoreCase);
33
34        Console.WriteLine(result);
35    }
36}

Path.GetFullPath resolves relative segments such as . and ... Trimming the trailing separator keeps equivalent directory strings from failing an otherwise correct comparison.

Pick the Correct Case-Sensitivity Rule

Path comparison is not the same on every platform. Windows filesystems are usually case-insensitive, while Linux filesystems are typically case-sensitive. That means one comparer does not fit every deployment.

csharp
1using System;
2using System.Runtime.InteropServices;
3
4public static class PathComparerFactory
5{
6    public static StringComparer GetPathComparer()
7    {
8        return RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
9            ? StringComparer.OrdinalIgnoreCase
10            : StringComparer.Ordinal;
11    }
12}

You can combine this with the earlier helper:

csharp
var comparer = PathComparerFactory.GetPathComparer();
bool same = PathComparison.AreSameDirectory("./data", "/tmp/data", comparer);

If the code runs on Windows only, StringComparer.OrdinalIgnoreCase is normally the right choice. If it runs cross-platform, selecting the comparer at runtime avoids subtle bugs.

Use DirectoryInfo for Readable Code

You do not need DirectoryInfo just to compare strings, but it can make the normalization step more readable when code already works with filesystem objects.

csharp
1using System;
2using System.IO;
3
4public static class DirectoryInfoComparison
5{
6    public static bool AreSameDirectory(string first, string second)
7    {
8        var comparer = OperatingSystem.IsWindows()
9            ? StringComparer.OrdinalIgnoreCase
10            : StringComparer.Ordinal;
11
12        var firstFullName = new DirectoryInfo(first).FullName
13            .TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
14        var secondFullName = new DirectoryInfo(second).FullName
15            .TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
16
17        return comparer.Equals(firstFullName, secondFullName);
18    }
19}

This version still performs string comparison, but it keeps the intent clear when the rest of the code already deals with DirectoryInfo.

String Equality Is Not the Whole Story

Normalized strings are enough for many business cases, but they are not a full filesystem identity check. Symlinks, junctions, mount points, and network shares can make two different strings refer to the same real directory. If your application must detect true filesystem identity, string comparison is only a first filter.

That matters most for backup tools, sync engines, and file watchers. In those systems, you may need platform-specific APIs or resolved filesystem metadata rather than normalized text alone.

Compare Paths Only After Validation

Path normalization can throw if the input is malformed. It is better to fail early than to compare invalid strings and quietly accept garbage input.

csharp
1try
2{
3    var comparer = PathComparerFactory.GetPathComparer();
4    bool same = PathComparison.AreSameDirectory("../reports", "./reports", comparer);
5    Console.WriteLine(same);
6}
7catch (Exception ex)
8{
9    Console.WriteLine($"Path comparison failed: {ex.Message}");
10}

This is especially useful when paths come from users, config files, or external systems.

Common Pitfalls

  • Comparing raw strings without normalizing relative segments or trailing separators.
  • Using case-insensitive comparison on Linux or case-sensitive comparison on Windows by mistake.
  • Assuming two equal strings always mean the same physical directory when symlinks are involved.
  • Forgetting that malformed paths can throw during normalization.
  • Using culture-aware comparison instead of Ordinal or OrdinalIgnoreCase.

Summary

  • Compare normalized directory paths, not raw input strings.
  • Use Path.GetFullPath and trim trailing separators before equality checks.
  • Choose StringComparer.OrdinalIgnoreCase on Windows and StringComparer.Ordinal on case-sensitive systems.
  • 'DirectoryInfo.FullName can improve readability when you already work with directory objects.'
  • If symlinks or mount points matter, string comparison alone is not enough.

Course illustration
Course illustration

All Rights Reserved.