glob.glob() Silently Fails to Find a Filename Containing Brackets (tested)

Browsers commonly name duplicate downloads file[1].txt, image[2].jpg, and so on. We measured what happens when that exact filename is handed to glob.glob() as a lookup pattern, and it does not find the file you'd expect.

1. The literal filename matches a different file

import glob

# both files exist on disk:
#   /tmp/brackettest/file1.txt
#   /tmp/brackettest/file[1].txt

pattern = "/tmp/brackettest/file[1].txt"
print(glob.glob(pattern))
['/tmp/brackettest/file1.txt']

Measured: passing the file's own real name as the pattern returns the other file -- the one without brackets. glob parses [1] as a character class meaning "the single character 1," so the pattern actually means file1.txt, not file[1].txt. No error, no warning -- just a silently wrong result.

2. pathlib has the identical behaviour

from pathlib import Path

print([p.name for p in Path("/tmp/brackettest").glob("file[1].txt")])
['file1.txt']

Measured: Path.glob() uses the same bracket-class parsing as the glob module, so code that switched from one to the other for other reasons keeps this exact problem. If file1.txt doesn't happen to exist, the lookup returns an empty list instead -- making it look like file[1].txt itself is simply missing.

3. Fix: glob.escape() the literal filename first

import glob

escaped = glob.escape("/tmp/brackettest/file[1].txt")
print("escaped pattern:", escaped)
print(glob.glob(escaped))
escaped pattern: /tmp/brackettest/file[[]1].txt
['/tmp/brackettest/file[1].txt']

Measured: glob.escape() rewrites [ as the self-matching class [[], which finally matches the literal character. Any time a filename comes from outside your control -- scraped from a directory listing, a URL, an API response, user input -- and you're using it as a glob/Path.glob pattern rather than comparing strings directly, it needs glob.escape() first.

Frequently asked questions

Why does glob.glob() return the wrong file for a bracketed filename?

We measured glob treating [1] in the pattern as a character class (matching a single literal '1'), not as literal bracket characters -- so the pattern 'file[1].txt' actually searches for 'file1.txt'.

Does pathlib have the same bracket problem as glob?

Yes -- we confirmed Path.glob() uses the same character-class parsing, so passing a bracketed filename as a pattern silently looks for the wrong name there too.

How do I search for a filename that might contain special glob characters?

We confirmed glob.escape() on the filename (or full pattern) first makes glob.glob()/Path.glob() match the literal characters, including brackets, '*', and '?'.

Does glob.glob() raise an error for this kind of mismatch?

No -- we measured it returning either the wrong file (if one happens to match the character-class interpretation) or an empty list, with no exception in either case.

Which filenames commonly trigger this?

Browser-downloaded duplicate files are the most common real case we tested against -- names like file[1].txt, image[2].jpg -- but any filename containing [, ], *, ? or a POSIX character class name has the same risk unescaped.

Written with AI assistance. Measured on 2026-10-04 with Python 3.13.5's built-in glob and pathlib modules: created two files, 'file1.txt' and 'file[1].txt' (a common browser-duplicate-download naming pattern), then looked up the literal bracketed filename with glob.glob(), Path.glob(), and glob.escape(). PlainHeaders is our extension; Python's glob and pathlib modules are built in.