How to remove the extension from a filename in Python

Learn how to remove extensions from filenames in Python. Discover multiple methods, tips, real-world applications, and common error fixes.

How to remove the extension from a filename in Python
Published on: 
Tue
Mar 10, 2026
Updated on: 
Fri
Mar 13, 2026
The Replit Team

Python developers often need to remove a file extension. This task helps streamline file processing and organize data. Python offers several simple methods to handle this operation efficiently.

In this article, we'll explore several techniques to remove file extensions, from simple string methods to the pathlib module. You'll find practical tips, see real-world applications, and get debugging advice to confidently handle filename manipulation in your projects.

Using os.path.splitext() function

import os
filename = "document.pdf"
name_without_extension = os.path.splitext(filename)[0]
print(name_without_extension)--OUTPUT--document

The os.path.splitext() function is a reliable tool from Python's os module designed specifically for path manipulation. It intelligently splits a filename into a two-part tuple containing the main name and the extension. By accessing the first element with [0], you cleanly isolate the base name.

This method is more robust than simple string splitting. It correctly handles filenames that might contain multiple dots, like archive.tar.gz, by only splitting at the final dot. This ensures you're always removing just the file extension, making your code more predictable.

String manipulation techniques

If you prefer a more hands-on approach or need extra flexibility, Python’s built-in string methods offer another powerful way to tackle filename manipulation.

Using string slicing with rfind()

filename = "report.csv"
position = filename.rfind(".")
name_without_extension = filename[:position] if position > 0 else filename
print(name_without_extension)--OUTPUT--report

This method gives you direct control over string manipulation. The rfind(".") function finds the index of the last dot in the filename, which is key for correctly identifying the extension, especially in names like archive.tar.gz.

  • Using this index, the slice filename[:position] extracts everything before the dot.
  • The conditional check if position > 0 acts as a safeguard. It ensures your code gracefully handles files without extensions or hidden files that start with a dot, like .bashrc.

Using the split() method

filename = "image.png"
name_without_extension = filename.split(".")[0]
print(name_without_extension)--OUTPUT--image

The split(".") method provides a simple way to break a string into a list, using the dot as the separator. By accessing the first element with [0], you get everything before the first dot, effectively isolating the base name for simple filenames.

  • While straightforward, this method has a key limitation. It splits at every dot, so a file named archive.tar.gz would incorrectly result in archive. It’s best used when you’re confident your filenames contain only a single extension.

Using the rsplit() method with limit

filename = "data.backup.txt"
name_without_extension = filename.rsplit(".", 1)[0]
print(name_without_extension)--OUTPUT--data.backup

The rsplit() method offers a more precise alternative to split(). By splitting from the right, it targets the file extension directly. The key is the second argument, 1, which limits the operation to a single split. This ensures that only the final extension is separated from the filename, making it a robust solution.

  • The code rsplit(".", 1) splits the string at the last dot, creating a list like ['data.backup', 'txt'].
  • Accessing the first item with [0] then isolates the base name, correctly handling files with multiple dots.

Modern and advanced techniques

If you need more power than traditional string methods provide, Python’s modern pathlib module and regular expressions offer elegant and robust solutions.

Using pathlib.Path for modern file handling

from pathlib import Path
filename = "presentation.pptx"
name_without_extension = Path(filename).stem
print(name_without_extension)--OUTPUT--presentation

The pathlib module offers an object-oriented approach to filesystem paths, making your code cleaner and more intuitive. When you create a Path object from a filename, you gain access to several helpful attributes for path manipulation.

  • The .stem attribute is a standout feature—it directly gives you the filename without its final extension.
  • It intelligently handles files with multiple dots, like archive.tar.gz, by returning archive.tar.
  • This approach is clean, reliable, and part of a larger, powerful library for file operations.

Using regular expressions

import re
filename = "notes.md"
name_without_extension = re.sub(r'\.[^.]+$', '', filename)
print(name_without_extension)--OUTPUT--notes

For complex pattern matching, you can use regular expressions. The re.sub() function finds text that matches a pattern and replaces it. Here, it finds the file extension and replaces it with an empty string, which effectively deletes it.

  • The pattern r'\.[^.]+$' is designed to precisely identify the extension.
  • It looks for a literal dot \. followed by one or more non-dot characters [^.]+ at the very end of the string $.

This approach gives you maximum control, though it's often more complex than needed for this specific task.

Creating a flexible extension remover

def remove_extensions(filename, all_extensions=False):
if all_extensions:
return filename.split('.')[0]
return os.path.splitext(filename)[0]

print(remove_extensions("archive.tar.gz", False))
print(remove_extensions("archive.tar.gz", True))--OUTPUT--archive.tar
archive

By combining previous methods, you can create a more versatile tool. This remove_extensions function uses a boolean flag, all_extensions, to let you choose how to handle files with multiple dots, like archive.tar.gz.

  • When the flag is True, the function uses split('.') to remove all extensions, returning just the base name.
  • When False, it defaults to using os.path.splitext(), which only removes the final extension.

This approach gives you a single, adaptable solution for different filename formats.

Move faster with Replit

Replit is an AI-powered development platform that transforms natural language into working applications. Describe what you want to build, and Replit Agent creates it—complete with databases, APIs, and deployment.

For the filename manipulation techniques we've explored, Replit Agent can turn them into production-ready tools:

  • Build a batch file organizer that renames files by removing extensions, preparing them for a new system.
  • Create a digital asset manager that standardizes filenames using pathlib.Path before uploading them to cloud storage.
  • Deploy a data ingestion utility that cleans up log file names by stripping extensions before parsing their contents.

Describe your app idea, and Replit Agent writes the code, tests it, and fixes issues automatically, all in your browser.

Common errors and challenges

When removing file extensions, you might run into a few common pitfalls, but they're easy to navigate with the right approach.

Handling files with no extension using split()

A frequent issue arises when a filename, like "README", has no extension. If your code assumes a dot is always present, using a method like split('.') can lead to unexpected behavior or errors if you try to access parts of the split that don't exist. It's a good practice to first check if a dot is even in the filename before you attempt to split it.

Handling filenames with multiple dots

Filenames with multiple dots, such as archive.tar.gz, often trip up simpler methods. Using split('.') will break the string at every dot, which can leave you with just the first part of the name—archive in this case—when you actually wanted archive.tar. This is why functions like os.path.splitext() and rsplit('.', 1) are generally safer, as they're designed to isolate only the final extension.

Dealing with case sensitivity in file extensions

File extensions aren't always lowercase. You might encounter .JPG, .PNG, or even mixed-case variations. If your logic is case-sensitive and only looks for .jpg, it will fail to identify the extension correctly. A simple and effective solution is to convert the entire filename to lowercase using the .lower() method before you process it. This ensures your code works consistently, regardless of how the extension is cased.

Handling files with no extension using split()

Using the split('.') method on a filename without an extension is a classic tripwire. If you try to access the part after the dot, your code will raise an IndexError because that list item simply doesn't exist. The following example demonstrates this exact scenario.

filename = "README"
try:
extension = filename.split(".")[1]
print(f"Extension: {extension}")
except IndexError:
print("Error: No extension found")

The code splits "README" into a list with just one item. When it tries to access the second item with [1], Python raises an IndexError. Here’s how you can handle this case more gracefully.

filename = "README"
parts = filename.split(".")
extension = parts[1] if len(parts) > 1 else ""
print(f"Extension: {extension or 'No extension found'}")

This solution proactively avoids an IndexError by checking the list's length after the split. The code first splits the filename into a list called parts. Then, the conditional check len(parts) > 1 confirms if a dot was actually found. If true, you can safely grab the extension; otherwise, it assigns an empty string, neatly sidestepping the error. This is a crucial safeguard whenever you’re processing filenames that might not have an extension.

Handling filenames with multiple dots

Filenames with multiple dots, such as archive.tar.gz, can easily trip up basic string methods. When you use split('.') and grab the first item with [0], you might not get the result you expect. The following example demonstrates this common pitfall.

filename = "data.backup.txt"
name_without_extension = filename.split(".")[0]
print(name_without_extension) # Outputs: data

The split('.') method breaks the filename into multiple parts. Taking only the first element with [0] incorrectly discards backup along with the extension, leaving just data. The following example shows a more precise solution.

filename = "data.backup.txt"
name_without_extension = filename.rsplit(".", 1)[0]
print(name_without_extension) # Outputs: data.backup

The rsplit('.', 1) method provides a more precise solution. It splits the string from the right, but the 1 limits the operation to a single split, isolating only the final extension. By taking the first element with [0], you correctly get data.backup. This approach is perfect for filenames with multiple dots, like versioned backups or compressed archives, ensuring you only remove the true file extension while keeping the rest of the name intact.

Dealing with case sensitivity in file extensions

File extensions aren't always lowercase. You might encounter .JPG or .PDF, which can cause problems if your code is case-sensitive. A simple check for .pdf will miss files with different casing, leading to incomplete or incorrect results.

The following code demonstrates this issue. Notice how a list comprehension using f.endswith('.pdf') fails to find any files because it's looking for an exact, lowercase match.

files = ["report.PDF", "image.Jpg", "document.txt"]
pdf_files = [f for f in files if f.endswith('.pdf')]
print(pdf_files) # Outputs: []

The code's case-sensitive check for .pdf causes it to miss variations like .PDF, resulting in an empty list. The following example demonstrates a more reliable way to find all relevant files.

files = ["report.PDF", "image.Jpg", "document.txt"]
pdf_files = [f for f in files if f.lower().endswith('.pdf')]
print(pdf_files) # Outputs: ['report.PDF']

The fix is to make your check case-insensitive. By chaining the .lower() method before .endswith('.pdf'), you standardize the filename before making the comparison.

  • This simple change ensures files like report.PDF are correctly identified.
  • It's a crucial safeguard when handling files from user uploads or different operating systems, where you can't rely on consistent casing.

This makes your file processing logic far more robust.

Real-world applications

These techniques are the building blocks for automating practical tasks, from batch renaming files to analyzing project structures.

Batch processing images in a directory

You can easily process a folder of images by looping through each file, stripping the extension with os.path.splitext(), and then applying an action like resizing or renaming.

import os

for filename in os.listdir("images"):
base_name = os.path.splitext(filename)[0]
if filename.lower().endswith(('.jpg', '.png')):
print(f"Processing: {base_name}")

This script automates file handling within a directory. It uses os.listdir() to scan the "images" folder and process each filename. Before doing anything, it isolates the base name using os.path.splitext() and then filters the files with a conditional check.

  • The if statement uses filename.lower().endswith(('.jpg', '.png')) to find files ending with either extension.
  • This check is case-insensitive because .lower() converts the name first, so it won't miss files like Photo.JPG.

This is a common and robust pattern for targeting specific files.

Analyzing file types in a project directory with os.walk()

You can use os.walk() to recursively scan an entire project directory, making it easy to tally up all the different file types.

import os
from pathlib import Path

file_types = {}
for root, _, files in os.walk("project"):
for file in files:
ext = Path(file).suffix
file_types[ext] = file_types.get(ext, 0) + 1

print(file_types)

This script recursively scans the "project" directory to create a tally of all file types. It uses os.walk() to travel through every folder, and for each file, Path(file).suffix efficiently extracts its extension, like .py or .md.

  • A dictionary named file_types keeps track of the counts.
  • The expression file_types.get(ext, 0) + 1 is a concise way to update the tally. It fetches the current count for an extension or defaults to zero if it's the first time seeing it, then adds one.

Get started with Replit

Now, turn these techniques into a real tool. Describe what you want, like “a batch renamer that removes extensions from all files in a directory” or “a utility that cleans up filenames with multiple dots.”

Replit Agent writes the code, tests for errors, and deploys your app. Start building with Replit.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started for free

Create & deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.