filenames
sorting
arrays
strings with numbers
programming

Sorting an array of filenames containing strings with numbers

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

Sorting filenames that contain numbers is harder than it looks because ordinary string sorting is lexicographical, not numeric. That is why a naive sort puts file10.txt before file2.txt: it compares character by character and sees "1" before "2".

What people usually want is natural sorting, where digit runs are treated as numbers. That makes filenames appear in the order a human expects.

Why Lexicographical Sorting Fails

Consider this list:

python
files = ["file1.txt", "file10.txt", "file2.txt", "file20.txt"]
print(sorted(files))

The result is:

python
['file1.txt', 'file10.txt', 'file2.txt', 'file20.txt']

This is not a bug. It is exactly how string comparison works. The problem is that filenames often mix text and numeric meaning, so a raw string comparison does not match user expectations.

Build a Natural Sort Key

The usual fix is to split the filename into alternating text and number pieces, then convert the number pieces into integers.

python
1import re
2
3
4def natural_key(filename):
5    parts = re.split(r"(\d+)", filename)
6    key = []
7
8    for part in parts:
9        if part.isdigit():
10            key.append(int(part))
11        else:
12            key.append(part.lower())
13
14    return key
15
16
17files = ["file1.txt", "file10.txt", "file2.txt", "file20.txt"]
18print(sorted(files, key=natural_key))

That produces:

python
['file1.txt', 'file2.txt', 'file10.txt', 'file20.txt']

This works because Python compares lists element by element. Text stays as normalized text, while digit sequences are compared as actual integers.

Why This Pattern Works Well

Suppose the filename is image12_part3.png. The regex split produces pieces like:

  • '"image"'
  • '"12"'
  • '"_part"'
  • '"3"'
  • '".png"'

After conversion, the sort key becomes a mixed list of text and integers. That lets Python compare 12 numerically instead of comparing "12" as a raw string fragment.

This handles many everyday filename sets cleanly, including numbered exports, page scans, and build artifacts.

A Library Option

If you do this often, a specialized library can be more convenient. In Python, natsort is a popular choice:

python
1from natsort import natsorted
2
3files = ["file1.txt", "file10.txt", "file2.txt", "file20.txt"]
4print(natsorted(files))

That saves you from maintaining your own key logic, especially if you care about locale-aware behavior, signed numbers, or more unusual string patterns.

When Filenames Have Multiple Number Segments

Natural sorting is especially valuable when names contain more than one numeric fragment, such as scan_2_page_10.png. A simple lexicographical sort gets these wrong quickly, while the tokenized key approach still works because each digit run is compared numerically in order.

That makes the same technique useful for versioned files, exported reports, and numbered page assets, not just for trivial file1 and file2 examples.

Edge Cases to Think About

Natural sorting is still a policy decision. For example:

  • should uppercase and lowercase be treated the same,
  • should file001 and file1 be considered equivalent,
  • should extensions influence sorting before or after the numeric part,
  • do negative numbers or decimals appear in the names.

The simple regex key above is a strong default, but it is still a rule set you control.

Common Pitfalls

  • Using plain sorted() and expecting human-friendly numeric ordering automatically.
  • Forgetting to convert digit substrings to integers, which leaves the sort effectively lexicographical.
  • Ignoring case normalization when filenames may differ by capitalization.
  • Assuming one natural-sort rule fits every naming convention.
  • Reimplementing a complicated sorter when a library such as natsort already solves the problem well.

Summary

  • Ordinary string sorting compares characters, not numeric meaning.
  • Natural sorting treats digit runs inside filenames as integers.
  • A regex-based key function is a simple and effective solution in Python.
  • Libraries such as natsort are useful when filename patterns are more complex.
  • The right sort order depends on the filename conventions you actually have.

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.