# No matter what the os/path format is, extract the file name from the path.

## Problem

Which Python module can I use to extract filenames from paths, regardless of what operating system I’m using or what path format I’m using?

For example, I’d like c: to be returned by all of these pathways.

a/b/c/
a/b/c
\a\b\c
\a\b\c\
a\b\c
a/b/../../a/b/c/
a/b/../../a/b/c


## Solution #1

In fact, there’s a function that does exactly what you’re looking for.

import os
print(os.path.basename(your_path))


WARNING: When using os.path.basename() to get the base name from a Windows styled path (e.g. “C:myfile.txt”) on a POSIX system, the complete path will be returned.

Below is an example of an interactive Python shell on a Linux host:

Python 3.8.2 (default, Mar 13 2020, 10:14:16)
[GCC 9.3.0] on linux
>>> import os
>>> filepath = "C:\\my\\path\\to\\file.txt" # A Windows style file path.
>>> os.path.basename(filepath)
'C:\\my\\path\\to\\file.txt'


## Solution #2

Others’ suggestions of using os.path.split or os.path.basename won’t always work: if you run the script on Linux and try to process a standard Windows-style path, it will fail.

The path separator in Windows paths can be either a backslash or a forward slash. As a result, on all systems, the ntpath module (which is similar to os.path on Windows) will function for all(1) paths.

import ntpath
ntpath.basename("a/b/c")


Of course, if the file ends with a slash, the basename will be empty, so make your own function to deal with it:

def path_leaf(path):


Verification:

>>> paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
...     'a/b/../../a/b/c/', 'a/b/../../a/b/c']
>>> [path_leaf(path) for path in paths]
['c', 'c', 'c', 'c', 'c', 'c', 'c']


(1) One caveat: filenames on Linux may contain backslashes. So on linux, r’a/b\c’ always refers to the file b\c in the a folder, while on Windows, it always refers to the c file in the b subfolder of the a folder. So when both forward and backward slashes are used in a path, you need to know the associated platform to be able to interpret it correctly. In practice it’s usually safe to assume it’s a windows path since backslashes are seldom used in Linux filenames, but keep this in mind when you code so you don’t create accidental security holes.

## Solution #3

The function you’re looking for is os.path.split.

head, tail = os.path.split("/tmp/d/a.dat")

>>> print(tail)
a.dat
/tmp/d


## Solution #4

In python 3

>>> from pathlib import Path
>>> Path("/tmp/d/a.dat").name
'a.dat'


## Solution #5

import os