bytes.rfind()
The search runs from the right, but the answer is an ordinary left-counted offset. The standard tool for splitting on the last separator.
Demo
In abcabc the byte b sits at 1 and 4; rfind returns 4, the last one, while find would return 1. The number is still counted from the left — only the scan direction changed. An absent sequence gives -1. The empty sequence matches at every position, so its last match is the very end, giving the length. The multi-byte case shows the offset is in bytes: the last l in héllo is at byte 4, not character 3.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| sub | bytes | int | yes | Byte sequence to locate. An int from 0 to 255 searches for that single byte. |
| start | int | no (0) | Left boundary of the searched region. Still the LEFT boundary, even though the scan is from the right. |
| end | int | no (len) | Right boundary, exclusive. |
Return value
int — Byte offset of the last occurrence of sub, or -1 if absent. Never raises for a missing value.
Common patterns
leaf = path[path.rfind(b'/') + 1:]
i = name.rfind(b'.') ext = name[i:] if i != -1 else b''
i = data.rfind(sub) while i != -1: handle(i) i = data.rfind(sub, 0, i)
Examples
Pitfalls
b'abcabc'.rfind(b'b')
len(d) - d.rfind(b'b') - 1
d = b'abc' d[d.rfind(b'z') + 1:]
i = d.rfind(b'z') leaf = d[i + 1:] if i != -1 else d
b'abcabc'.rfind(b'b', 2)
b'abcabc'.rfind(b'b', 0, 4)
When to use
- Splitting on the LAST separator — paths, extensions, host:port
- Absence is normal and should give -1 rather than raise
- Walking matches from the end backwards
- Absence is an error → rindex
- The FIRST occurrence → find
- Splitting a path → os.path or pathlib handle the edge cases
Notes
FAQ
Because rfind returns a position, not a distance. Positions count from zero at the left regardless of scan direction, which is what makes the result directly usable in a slice.
d = b'a/b/c' d[d.rfind(b'/') + 1:] # b'c'