Non-alphanumeric list order from os.listdir
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
os.listdir() returns directory entries in whatever order the operating system provides. That means names beginning with punctuation, spaces, digits, or mixed case can appear in an order that looks random if you expected a human-friendly alphabetical list.
os.listdir() Does Not Promise Sorted Output
The most important fact is simple: os.listdir() is not a sorting API. It asks the file system for the directory entries and returns them as a Python list. The order may depend on file system internals, creation history, or platform details.
This short example shows the behavior clearly:
The output is a list of names, but Python does not guarantee any particular sequence. If your program depends on order, you must sort it explicitly.
Why Non-Alphanumeric Names Look Strange
Once you call sorted(), the next surprise is how punctuation and digits are ordered. By default, Python sorts strings lexicographically by Unicode code point, not by "what a user probably meant."
That means:
- names starting with punctuation often come before letters
- uppercase and lowercase may not group the way you expect
- '
"10.txt"comes before"2.txt"in simple lexicographic order'
Example:
A default sort is deterministic, but not necessarily natural for filenames. It is still much better than relying on raw os.listdir() order because at least it is predictable.
Use the Right Sort for the Job
If you only need a stable alphabetical order, a normal sort is enough:
If you want case-insensitive ordering, use str.casefold as the key:
That makes the order less surprising when names differ only by case. It still does not treat embedded numbers as numbers, which is why "10.txt" still sorts before "2.txt".
Natural Sorting for Numeric Filenames
When filenames contain numeric parts, a natural sort is usually closer to user expectations. The idea is to split the name into text and digit chunks, then compare digit chunks numerically.
With that key function, "2.txt" sorts before "10.txt", which is what most people expect when reading filenames.
This is also the place where non-alphanumeric characters matter. If your naming scheme includes prefixes such as _, -, or #, decide whether those characters should affect order. If not, your key function can strip or normalize them before sorting.
Locale-Aware Sorting When Human Language Matters
Some applications need an order based on language conventions rather than raw code points. Python can do that with the locale module, although it depends on the system locale being configured correctly.
This is useful in user-facing tools, but it also makes behavior depend on the machine's locale settings. For build scripts and data pipelines, a deterministic custom key is often safer.
Prefer Explicit Ordering in Production Code
The broader lesson is that directory iteration and ordering are separate concerns. os.listdir() answers "what exists," not "how should it be ordered." If the order matters for correctness, reports, or tests, express that order in code.
For new code, pathlib.Path.iterdir() is often more convenient than os.listdir(), but the rule is exactly the same: the entries are not inherently sorted.
That version is clearer when you need both the path objects and an explicit ordering rule.
Common Pitfalls
The first mistake is assuming os.listdir() returns alphabetically sorted names. Another is applying sorted() and then being surprised that punctuation or numeric substrings do not behave like a human-friendly file browser. Developers also write tests against the raw os.listdir() result and end up with order-dependent failures across machines or file systems. A final issue is using locale-aware sorting in automation without realizing the result may vary between environments.
Summary
- '
os.listdir()returns entries in an unspecified order.' - Default Python sorting is lexicographic by Unicode code point, not natural or locale-aware.
- Use
sorted(entries)for a stable baseline order. - Use
key=str.casefoldfor case-insensitive ordering and a custom key for natural numeric sorting. - If order matters for correctness, define it explicitly instead of relying on directory iteration order.
Related reading
- Non-blocking solution to the dining philosophers
- Non-intersecting line segments while minimizing the cumulative length
- Non-recursive depth first search algorithm
- Non-recursive implementation of Flood Fill algorithm?
- Normal arguments vs. keyword arguments
- Normalized Cross-Correlation in Python
- Non-Recursive Merge Sort
- Non-recursive merge sort with two nested loops - how?

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.