Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

C# Dictionary

  1. Home
  2. C# Dictionary
  3. Path.Combine() / Path.GetFileName()

Path.Combine() / Path.GetFileName()

Since: C# 1.0(2002)

Path.Combine() safely joins file paths, and Path.GetFileName() extracts the filename portion from a path.

Syntax

// Joins paths using the OS path separator automatically
Path.Combine(string path1, string path2)
Path.Combine(params string[] paths)

// Gets the filename including the extension from a path
Path.GetFileName(string path)

// Gets the filename without the extension
Path.GetFileNameWithoutExtension(string path)

// Gets the extension (with a leading dot)
Path.GetExtension(string path)

// Gets the directory portion of the path
Path.GetDirectoryName(string path)

Method List

MethodDescription
Path.Combine(path1, path2)Joins two or more paths. Automatically inserts the OS separator (\ on Windows, / on Linux/Mac).
Path.GetFileName(path)Returns only the filename (with extension) from the path string.
Path.GetFileNameWithoutExtension(path)Returns the filename without the extension.
Path.GetExtension(path)Returns the extension (e.g., .txt). Returns an empty string if there is no extension.
Path.GetDirectoryName(path)Returns the directory portion of the path, excluding the filename.
Path.GetFullPath(path)Converts a relative path to an absolute path.
Path.GetTempPath()Returns the path of the system's temporary file directory.

Sample Code

Program.cs
using System;
using System.IO;

// Joins paths using Path.Combine()
string folder = @"C:\Users\eva_user\documents";
string fileName = "report.txt";
string fullPath = Path.Combine(folder, fileName);
Console.WriteLine(fullPath); // C:\Users\eva_user\documents\report.txt

// Can join three or more paths at once
string savePath = Path.Combine(@"C:\data", "2024", "01", "log.csv");
Console.WriteLine(savePath); // C:\data\2024\01\log.csv

// Extracts filename components with Path.GetFileName() and related methods
string path = @"C:\Users\eva_user\documents\report.txt";
Console.WriteLine(Path.GetFileName(path)); // report.txt
Console.WriteLine(Path.GetFileNameWithoutExtension(path)); // report
Console.WriteLine(Path.GetExtension(path)); // .txt
Console.WriteLine(Path.GetDirectoryName(path)); // C:\Users\eva_user\documents

// Gets the system temporary directory
string tempDir = Path.GetTempPath();
Console.WriteLine(tempDir); // e.g., C:\Users\eva_user\AppData\Local\Temp\

This produces the following output:

dotnet script path_combine_getfilename.csx
C:\Users\eva_user\documents\report.txt
C:\data\2024\01\log.csv
report.txt
report
.txt
C:\Users\eva_user\documents
C:\Users\eva_user\AppData\Local\Temp\

The output above is from a Windows environment. On macOS/Linux, the separator is a forward slash (/).

Practical Pattern: Generating Dated Log File Paths

A pattern for generating a log file path based on the current date. Produces a consistent path no matter how many times it is called.

LogPathBuilder.cs
using System;
using System.IO;

string logDir = Path.Combine(
    Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
    "EvaApp",
    "logs"
);

// Generates a dated log filename
string logFileName = $"app_{DateTime.Today:yyyyMMdd}.log";
string logFilePath = Path.Combine(logDir, logFileName);

Console.WriteLine($"Log directory: {logDir}");
Console.WriteLine($"Log file: {logFilePath}");

// Creates the directory and appends to the log file
Directory.CreateDirectory(logDir);
File.AppendAllText(logFilePath, $"[{DateTime.Now:HH:mm:ss}] Started\n");

// Breaks down the path for verification
Console.WriteLine($"Filename: {Path.GetFileName(logFilePath)}");
Console.WriteLine($"Extension: {Path.GetExtension(logFilePath)}");
Console.WriteLine($"Directory: {Path.GetDirectoryName(logFilePath)}");

// Cleanup
Directory.Delete(logDir, recursive: true);

This produces the following output:

dotnet script log_path_builder.csx
Log directory: /Users/eva_user/Library/Application Support/EvaApp/logs
Log file: /Users/eva_user/Library/Application Support/EvaApp/logs/app_20240115.log
Filename: app_20240115.log
Extension: .log
Directory: /Users/eva_user/Library/Application Support/EvaApp/logs

Practical Pattern: Filtering Files by Extension

A pattern for processing only files with specific extensions from a directory listing.

ExtensionFilter.cs
using System;
using System.IO;
using System.Linq;

// Sets up test files
string testDir = "test_assets";
Directory.CreateDirectory(testDir);
File.WriteAllText(Path.Combine(testDir, "shinji.png"), "png");
File.WriteAllText(Path.Combine(testDir, "rei.jpg"), "jpg");
File.WriteAllText(Path.Combine(testDir, "asuka.png"), "png");
File.WriteAllText(Path.Combine(testDir, "kaworu.txt"), "txt");
File.WriteAllText(Path.Combine(testDir, "misato.json"), "json");

// Lists all files and their extensions
string[] allFiles = Directory.GetFiles(testDir);
Console.WriteLine("--- All files ---");
foreach (string f in allFiles)
{
    string name = Path.GetFileName(f);
    string ext = Path.GetExtension(f);
    Console.WriteLine($"  {name} (ext: {ext})");
}

// Extracts image files (.png, .jpg) only
var imageFiles = allFiles
    .Where(f => Path.GetExtension(f).ToLower() is ".png" or ".jpg")
    .Select(f => Path.GetFileName(f))
    .ToList();

Console.WriteLine($"--- Image files ({imageFiles.Count}) ---");
foreach (string img in imageFiles)
    Console.WriteLine($"  {img}");

// Cleanup
Directory.Delete(testDir, recursive: true);

This produces the following output:

dotnet script extension_filter.csx
--- All files ---
  asuka.png (ext: .png)
  kaworu.txt (ext: .txt)
  misato.json (ext: .json)
  rei.jpg (ext: .jpg)
  shinji.png (ext: .png)
--- Image files (3) ---
  asuka.png
  rei.jpg
  shinji.png

Common Mistakes

Common Mistake 1: Building Paths by String Concatenation

Manually concatenating strings to build paths leads to OS-specific separator issues and duplicate or missing slashes.

path_bad.cs
using System;
using System.IO;

// NG: Hardcoding separators causes OS-specific issues and duplicate slashes
string bad = "work" + "/" + "logs" + "/" + "app.log";
// Windows expects \ but / is used

// NG: Trailing slash causes double slash
string dir = "work/logs/";
string badPath = dir + "app.log"; // work/logs//app.log
path_good.cs
using System;
using System.IO;

// OK: Path.Combine() inserts the correct separator automatically
string good = Path.Combine("work", "logs", "app.log");
Console.WriteLine(good); // Windows: work\logs\app.log  macOS: work/logs/app.log

// OK: Handles trailing slashes correctly
string goodPath = Path.Combine("work/logs/", "app.log");
Console.WriteLine(goodPath); // work/logs/app.log (no duplication)

This produces the following output:

dotnet run
work/logs/app.log
work/logs/app.log

Common Mistake 2: GetDirectoryName Returning null

Passing a root path or a bare filename (with no directory part) to GetDirectoryName returns null or an empty string.

using System;
using System.IO;

// NG: Not accounting for null can cause a NullReferenceException
string rootPath = @"C:\";
string? dir1 = Path.GetDirectoryName(rootPath); // Returns null
Console.WriteLine(dir1 ?? "null"); // null

string bareFile = "report.txt"; // No directory part
string? dir2 = Path.GetDirectoryName(bareFile); // Returns "" (empty string)
Console.WriteLine($"Empty: '{dir2}'");

This produces the following output:

dotnet run
null
Empty: ''
using System;
using System.IO;

// OK: Add a null check
string? safeDir = Path.GetDirectoryName(@"C:\Users\eva_user\report.txt");
if (safeDir != null)
    Console.WriteLine($"Directory: {safeDir}");

This produces the following output:

dotnet run
Directory: C:\Users\eva_user

Overview

Path.Combine() is the safe way to join paths compared to string concatenation. It automatically corrects duplicate or missing separators, so the same code works on Windows, Linux, and Mac.

Manually concatenating paths with path1 + "\\" + path2 is prone to OS-specific separator differences, so always use Path.Combine().

For reading and writing files, see File.ReadAllText() / File.WriteAllText().

If you find any errors or copyright issues, please .