Advanced

Finding many files

A folder holds names you learn at run time. Listing, filtering, and recursing are the steps that turn a tree into a list you can process.

What you will see

True

About 2 min of reading

Quick check

Before this new lesson, one small question about the lesson you just finished. Recall it, do not look it up.

Try It

Inspect a file list.

1

First sorted name.

names = ["b.txt", "a.txt"] print(sorted(names)[0])

Before you run it, say out loud what it will print. Then open the answer.

What it prints
a.txt
2

Names kept.

names = ["a.txt", "b.bin"] keep = [x for x in names if x.endswith(".txt")] print(len(keep))

Before you run it, say out loud what it will print. Then open the answer.

What it prints
1
3

No matches.

import glob print(len(glob.glob("none-*.txt")))

Before you run it, say out loud what it will print. Then open the answer.

What it prints
0
4

Files counted.

n = 0 for root, dirs, files in os.walk("."): n += len(files) print(n > 0)

Before you run it, say out loud what it will print. Then open the answer.

What it prints
True

Put it in order

Before you write anything, put these lines back in the right order. Click a line to move it up one step. This support step is easier than writing code from scratch, and it is here to make the last example stick.

Data Flow

A folder is listed at run time. Patterns match names, walk visits every level, and an empty result is a valid answer.
1 list the folder
↓
2 filter the names
↓
3 walk deeper
↓
4 sort when needed
Line by line

Read the first example one line at a time. A line that prints shows what appears on screen; the rest set things up quietly.

names = ["b.txt", "a.txt"] sets nothing on screen
print(sorted(names)[0]) a.txt
Why this works
Order is not free

A listing comes in whatever order the folder gives. Sort when output feeds a diff or a person, and do not rely on it otherwise.

Empty is a result

A pattern with no matches is a valid answer. Treat zero files as a case, not as a crash.

Examples

Match a pattern

import glob
names = glob.glob("*.txt")
print(len(names))

The pattern is matched against names. An empty result is a real answer.

Two levels deep

import glob
names = glob.glob("*/*.txt")
print(len(names))

One star is one level. A deeper tree needs a recursive walk, not more stars.

Walk the tree

import os
n = 0
for root, dirs, files in os.walk("."):
    n += len(files)
print(n)

walk visits every folder. The count is every file under the start.

Sort for order

names = ["b.txt", "a.txt"]
print(sorted(names)[0])

Listing order is not guaranteed. Sort when the order of output matters.

Skip what you cannot read

names = ["a.txt", "b.bin"]
keep = [x for x in names if x.endswith(".txt")]
print(len(keep))

Filter before opening. A folder of unreadable files should not stop the run.

A folder that is empty

import glob
names = glob.glob("none-*.txt")
print(len(names))

Zero matches is not an error. Code that assumes one file fails on the empty case.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← Streaming a big file
Previous Lesson
Streaming a big file
Next Lesson
Failures that matter
Failures that matter →