Skip to content
Happy Programming Guide
Start learning
Python

How to Get File Name from a Path in Python

Four ways to pull the file name out of a path in Python, when to use pathlib instead of os.path, and how to drop the extension.

An open laptop on a wooden desk

The short answer: use pathlib. Path("/home/ana/report.pdf").name gives you report.pdf, and .stem gives you report without the extension. If you are working in older code, os.path.basename() does the same job. Everything below is the detail around those two lines — the edge cases, the Windows quirks, and why you should stop using string splitting for this.

The modern way: pathlib#

Python
from pathlib import Path

p = Path("/home/ana/documents/report.pdf")

print(p.name)     # report.pdf
print(p.stem)     # report
print(p.suffix)   # .pdf
print(p.parent)   # /home/ana/documents

Four attributes, no function calls, no imports beyond pathlib. This works identically on Windows, macOS and Linux:

Python
p = Path(r"C:\Users\ana\Documents\report.pdf")
print(p.name)   # report.pdf
print(p.stem)   # report

The r prefix makes it a raw string so the backslashes are not treated as escape characters.

The older way: os.path#

Plenty of existing code uses os.path, and it is still perfectly correct:

Python
import os

path = "/home/ana/documents/report.pdf"

print(os.path.basename(path))                        # report.pdf
print(os.path.dirname(path))                         # /home/ana/documents
print(os.path.splitext(os.path.basename(path))[0])   # report
print(os.path.splitext(path)[1])                     # .pdf

Getting the name without the extension takes two nested calls, which is the main reason pathlib reads better. os.path.splitext returns a tuple of everything before the dot and the extension, so index 0 is the stem and index 1 is the suffix.

What not to do#

Python
path = "/home/ana/report.pdf"
name = path.split("/")[-1]     # works here, fails on Windows

This is the answer people reach for first and it is a genuine bug on Windows, where paths use backslashes:

Python
path = r"C:\Users\ana\report.pdf"
print(path.split("/")[-1])
# C:\Users\ana\report.pdf   - the whole path, unchanged

There was no forward slash to split on, so the “last piece” is the entire string. The code does not crash; it silently produces the wrong answer, which is worse. Use Path or os.path.basename and the platform difference disappears.

Files with more than one extension#

archive.tar.gz is the classic case:

Python
p = Path("backups/archive.tar.gz")

print(p.name)      # archive.tar.gz
print(p.stem)      # archive.tar     <- only strips the last suffix
print(p.suffix)    # .gz
print(p.suffixes)  # ['.tar', '.gz']

.stem removes one extension at a time. To strip all of them:

Python
def full_stem(path):
    p = Path(path)
    name = p.name
    for suffix in p.suffixes:
        if name.endswith(suffix):
            name = name[: -len(suffix)]
    return name


print(full_stem("backups/archive.tar.gz"))   # archive

Be careful with this on files like report.2024.01.pdf, where suffixes returns three entries and stripping them all leaves just report. Whether that is right depends entirely on your data.

Getting the name from a URL#

A URL is not a file path — it can carry a query string and a fragment, and Path will happily include them in the name. Parse it properly:

Python
from urllib.parse import urlparse, unquote
from pathlib import PurePosixPath

url = "https://example.com/files/annual%20report.pdf?v=3#page2"

name = PurePosixPath(unquote(urlparse(url).path)).name
print(name)   # annual report.pdf

urlparse discards the query and fragment, unquote turns %20 back into a space, and PurePosixPath is used because URLs always use forward slashes regardless of which operating system you are running on.

Listing names in a folder#

Python
from pathlib import Path

folder = Path("documents")

for item in folder.iterdir():
    if item.is_file():
        print(item.name)

# only PDFs, including subfolders
pdf_names = [p.name for p in folder.rglob("*.pdf")]

# names without extensions, sorted
stems = sorted(p.stem for p in folder.glob("*.csv"))

Quick reference#

You want pathlib os.path
File name with extension p.name os.path.basename(p)
File name without extension p.stem os.path.splitext(os.path.basename(p))[0]
Extension only p.suffix os.path.splitext(p)[1]
Containing folder p.parent os.path.dirname(p)
Absolute path p.resolve() os.path.abspath(p)

Questions people ask#

Does the file need to exist?

No. All of these operations are pure string manipulation on the path — nothing touches the disk. Path("nonsense/nothing.txt").stem returns nothing quite happily. Only methods like .exists(), .resolve() and .iterdir() read the filesystem.

Should I use pathlib or os.path in new code?

Pathlib. It reads better, handles separators for you, and every function in the standard library that takes a path will accept a Path object directly. os.path is not deprecated, so there is no need to rewrite working code.

Why does Path.name return an empty string for my directory?

Almost always a trailing separator. Path("/var/log/") and Path("/var/log") behave differently for .name. Strip trailing slashes, or call .resolve() first.

How do I get just the file name inside an f-string?

Assign it first for readability: name = Path(path).name, then use the name in the f-string. Putting the whole expression inside the braces works but gets hard to read fast.

Where to go next#

Put this to work: a Python file organiser you can finish tonightBuild it

Keep reading

Keep going — pick your next guide

The fastest way to improve is to read one guide, then build the thing it describes. Start with the basics, or jump straight to a project.

Ask a question or share what worked

Your email address will not be published. Required fields are marked *