os.path.split
split(p) is (dirname(p), basename(p)) in one call. The cut is at the last separator, so a path ending in / has an empty tail. join(head, tail) gives back an equivalent path.
Common call
folder, name = os.path.split(path)
Returns
('/home/ada', 'notes.txt')
Replaces
path.rsplit('/', 1) — which mishandles '/', 'name' and Windows paths
Watch out
'/var/log/' splits into ('/var/log', '') — strip trailing slashes first if you want 'log'
os.path.split(path) → (head, tail)
→ tuple[str, str]
Demo
Live evaluation
POSIX rules via posixpath — the same output on every machine.
Try:
Inputs
pathstra POSIX path
Code
import posixpath posixpath.split('/home/ada/notes.txt')
Result
('/home/ada', 'notes.txt')
The head loses its trailing slashes, except when it is the root itself: split('/') is ('/', ''). A bare name has an empty head. posixpath treats a backslash as an ordinary character, so a Windows path is one long file name to it; ntpath splits at either slash and keeps 'C:\' together as the head.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| path | str | bytes | PathLike | yes | Any path. Nothing is checked on disk. |
Return value
tuple[str, str] — (head, tail): tail never contains a separator; head is the rest without trailing separators (unless it is the root).
Common patterns
Folder and name in one call
Tuple unpacking.
import os folder, name = os.path.split(path)
Last folder name of a directory path
Strip the trailing separator first.
import os last = os.path.split(path.rstrip(os.sep))[1]
All components
Loop until the head stops changing — or use pathlib: PurePath(p).parts.
import os def components(p): parts = [] while True: head, tail = os.path.split(p) if tail: parts.insert(0, tail) if head == p: if head: parts.insert(0, head) return parts p = head
Examples
1. Folder and file
import posixpath
posixpath.split('/home/ada/notes.txt')
Returns
('/home/ada', 'notes.txt')2. Trailing slash: empty tail
import posixpath
posixpath.split('/var/log/')
Returns
('/var/log', '')3. No folder
import posixpath
posixpath.split('notes.txt')
Returns
('', 'notes.txt')4. The root stays the root
import posixpath
posixpath.split('/')
Returns
('/', '')5. join undoes split
import posixpath
head, tail = posixpath.split('a/b/c.txt')
posixpath.join(head, tail)
Returns
'a/b/c.txt'6. Windows path with ntpath
import ntpath
ntpath.split(r'C:\Users\ada\notes.txt')
Returns
('C:\\Users\\ada', 'notes.txt')7. The drive root is kept
import ntpath
ntpath.split(r'C:\notes.txt')
Returns
('C:\\', 'notes.txt')Pitfalls
1. Expecting the last folder name from a path with a trailing slash
The tail is what follows the last separator — nothing, here.
split('/var/log/')
import posixpath posixpath.split('/var/log/')[1]
''
strip first
import posixpath posixpath.split('/var/log/'.rstrip('/'))[1]
'log'
2. Splitting by hand with rsplit
rsplit('/', 1) returns one item when there is no slash, and turns '/' into two empty strings.
rsplit('/', 1)
('notes.txt'.rsplit('/', 1), '/'.rsplit('/', 1))
(['notes.txt'], ['', ''])
posixpath.split
import posixpath (posixpath.split('notes.txt'), posixpath.split('/'))
(('', 'notes.txt'), ('/', ''))
When to use
Use it
- Getting folder and name of a str path together
Reach for something else
- Only one of the two → dirname / basename
- All components → PurePath(p).parts
- Extension → splitext
Notes
CPython impl
posixpath.split: i = p.rfind('/') + 1; head, tail = p[:i], p[i:]; trailing slashes are stripped from head unless it is all slashes. ntpath.split first takes off the drive and root with splitroot
Invariant
join(head, tail) refers to the same location as the original path (it may differ textually, e.g. doubled slashes)
FAQ
folder, name = os.path.split(path). With pathlib: p.parent and p.name.