Python
os.listdir
file sorting
non-alphanumeric
programming tips

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.

Practice algorithms

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:

python
1import os
2from pathlib import Path
3
4root = Path("demo_dir")
5root.mkdir(exist_ok=True)
6
7for name in ["b.txt", "_notes.txt", "10.txt", "2.txt", "A.txt"]:
8    (root / name).write_text("x", encoding="utf-8")
9
10print(os.listdir(root))

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:

python
entries = ["b.txt", "_notes.txt", "10.txt", "2.txt", "A.txt"]
print(sorted(entries))

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:

python
1import os
2
3entries = os.listdir("demo_dir")
4for name in sorted(entries):
5    print(name)

If you want case-insensitive ordering, use str.casefold as the key:

python
1import os
2
3entries = os.listdir("demo_dir")
4for name in sorted(entries, key=str.casefold):
5    print(name)

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.

python
1import os
2import re
3
4def natural_key(name: str):
5    parts = re.split(r"(\d+)", name)
6    return [int(part) if part.isdigit() else part.casefold() for part in parts]
7
8entries = os.listdir("demo_dir")
9for name in sorted(entries, key=natural_key):
10    print(name)

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.

python
1import locale
2
3locale.setlocale(locale.LC_COLLATE, "")
4entries = ["éclair.txt", "eagle.txt", "_draft.txt"]
5
6for name in sorted(entries, key=locale.strxfrm):
7    print(name)

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.

python
1from pathlib import Path
2
3for path in sorted(Path("demo_dir").iterdir(), key=lambda p: p.name.casefold()):
4    print(path.name)

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.casefold for 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
Course
Intermediate
27 lessons
15 hours
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 course
Track 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.

Practice algorithms

All Rights Reserved.