Glob в Python: как искать файлы по шаблонам и автоматизировать работу
Для кого эта статья:
- Python-разработчики, как начинающие, так и более опытные
- Студенты и обучающиеся в области программирования
Профессионалы, занимающиеся автоматизацией задач и обработкой данных
Каждый Python-разработчик рано или поздно сталкивается с необходимостью найти множество файлов определенного типа. Например, собрать все CSV с данными для анализа, обработать пакетно все изображения в папке или найти все Python-скрипты в проекте. Вручную перебирать сотни файлов — путь в никуда. Здесь на сцену выходит модуль glob — элегантный инструмент стандартной библиотеки Python, который решает задачу поиска файлов по шаблонам буквально в одну строку кода. 🔍 Мастерство использования glob отличает профессионального разработчика от новичка.
Хотите уверенно работать с файловой системой и автоматизировать рутинные задачи? Обучение Python-разработке от Skypro включает глубокое изучение работы с файловой системой, включая продвинутые техники использования модуля glob. Вы не только освоите теорию, но и примените знания в реальных проектах под руководством опытных менторов. Превратите хаос файлов в организованную систему уже через несколько недель практики!
Что такое модуль glob и зачем он нужен в Python
Модуль glob — это часть стандартной библиотеки Python, предназначенная для поиска файлов, соответствующих заданному шаблону. Его название происходит от термина "global pattern matching" (глобальное сопоставление с шаблоном), что точно описывает его функциональность. В основе glob лежит концепция Unix-подобных шаблонов, знакомая пользователям командной строки.
Отличие glob от обычного перебора файлов через os.listdir() заключается в возможности использовать специальные символы-шаблоны:
*— соответствует любой последовательности символов?— соответствует любому одиночному символу[seq]— соответствует любому символу из последовательности[!seq]— соответствует любому символу, не входящему в последовательность
Но зачем вообще нужен glob, если существуют методы os.walk() и os.listdir()? Преимущество glob — в лаконичности и выразительности. Сравните две реализации одной задачи:
| Поиск с использованием os | Поиск с использованием glob |
|---|---|
|
|
Очевидно, что второй вариант значительно компактнее и читабельнее. Glob — это инструмент, который делает код более декларативным: вы описываете, что хотите найти, а не как это сделать. 🧩
Алексей Воронов, Python-разработчик Я работал над проектом автоматизации отчётности, где требовалось ежедневно обрабатывать сотни CSV-файлов из разных департаментов. Названия файлов следовали формату "департаментдататип.csv", и каждый департамент имел свою специфику именования.
Первоначально я написал сложную функцию на 30+ строк с множеством условий и проверок имён файлов через регулярные выражения. Код работал, но был хрупким и трудно поддерживаемым.
Когда я открыл для себя модуль glob, всё изменилось. Задача поиска всех файлов определённого департамента за конкретную дату сократилась до:
PythonСкопировать кодfiles = glob.glob(f'data/{department}_*_{date}*.csv')А для обработки файлов по всем департаментам за месяц:
PythonСкопировать кодfiles = glob.glob(f'data/*_2023-06-*.csv')Код стал настолько понятным, что даже менеджеры без технического образования могли посмотреть на него и понять, что происходит. Время обработки сократилось, а количество потенциальных ошибок уменьшилось до нуля.

Основы использования glob.glob() для поиска файлов
Функция glob.glob() — основной инструмент модуля, возвращающий список путей к файлам, соответствующих заданному шаблону. Её использование интуитивно понятно даже начинающим программистам:
import glob
# Найти все Python-файлы в текущем каталоге
python_files = glob.glob('*.py')
# Найти все изображения
images = glob.glob('*.jpg') + glob.glob('*.png') + glob.glob('*.gif')
# Найти файлы с определенным префиксом
log_files = glob.glob('app_log_*.txt')
print(python_files) # ['script.py', 'utils.py', 'main.py', ...]
Важный момент: glob.glob() возвращает абсолютные пути, если шаблон начинается с корня файловой системы, и относительные пути в противном случае. Это поведение необходимо учитывать при дальнейшей обработке результатов.
Шаблоны можно комбинировать, создавая более сложные условия поиска:
'data/*/*.csv'— найдёт CSV-файлы во всех подкаталогах каталога 'data''**/test_*.py'— найдёт все тестовые Python-файлы в любом каталоге (с Python 3.5+)'docs/[0-9]*.txt'— найдёт текстовые файлы в каталоге 'docs', имена которых начинаются с цифры
Порядок выполнения поиска имеет значение: glob не сортирует результаты автоматически. Если вам нужен отсортированный список, используйте стандартную функцию sorted():
# Получить отсортированный список файлов
sorted_files = sorted(glob.glob('*.txt'))
Результаты функции glob.glob() можно сразу использовать в циклах для обработки найденных файлов — это типичный сценарий применения:
# Обработка всех CSV-файлов
for csv_file in glob.glob('data/*.csv'):
with open(csv_file, 'r') as f:
# Обработка содержимого файла
data = f.read()
print(f"Обрабатывается {csv_file}, размер: {len(data)} байт")
Glob особенно полезен при работе с данными для анализа, когда требуется собрать множество файлов из различных источников или каталогов. 📊
Продвинутый синтаксис шаблонов в модуле glob Python
Базовый синтаксис glob — это только верхушка айсберга. Истинная мощь модуля раскрывается при использовании продвинутых шаблонов поиска, которые позволяют точно указать, какие файлы вам нужны.
| Шаблон | Описание | Пример |
|---|---|---|
* | Соответствует любой последовательности символов (кроме разделителей пути) | *.txt — все текстовые файлы |
? | Соответствует любому одиночному символу | file?.txt — file1.txt, fileA.txt, но не file10.txt |
[abc] | Соответствует любому символу из указанных в скобках | file[123].txt — file1.txt, file2.txt, file3.txt |
[a-z] | Соответствует любому символу из диапазона | file[a-c].txt — filea.txt, fileb.txt, filec.txt |
[!abc] | Соответствует любому символу, кроме указанных | file[!123].txt — fileA.txt, file4.txt, но не file1.txt |
** | Рекурсивно соответствует всем каталогам (Python 3.5+) | **/*.py — все Python-файлы в любом подкаталоге |
Рассмотрим несколько интересных примеров использования сложных шаблонов:
# Файлы, имена которых содержат 3 цифры подряд
files_with_digits = glob.glob('*[0-9][0-9][0-9]*.*')
# Файлы с именами, начинающимися на гласные буквы
vowel_files = glob.glob('[aeiouAEIOU]*.*')
# Файлы с определенными расширениями (документы)
docs = glob.glob('*.[pd][do][cf]*') # Найдёт .pdf, .doc, .docx и т.д.
# Исключение определённых файлов
non_backup_files = glob.glob('*.[!b][!a][!k]') # Исключает файлы .bak
Комбинируя различные шаблоны, можно создавать чрезвычайно гибкие условия поиска. Например, найти все файлы журналов за определённый месяц:
# Поиск логов за май 2023 года (формат имени: log_YYYY-MM-DD.log)
may_logs = glob.glob('log_2023-05-??.log')
Один из малоизвестных, но мощных приёмов — использование альтернативных шаблонов с помощью фигурных скобок. Это не стандартная функциональность glob, но она доступна в некоторых реализациях UNIX, и её можно эмулировать в Python:
# Эмуляция альтернативных шаблонов через несколько вызовов glob
image_files = []
for ext in ['jpg', 'jpeg', 'png', 'gif']:
image_files.extend(glob.glob(f'*.{ext}'))
# Тот же результат с использованием генератора списков
image_files = [f for ext in ['jpg', 'jpeg', 'png', 'gif'] for f in glob.glob(f'*.{ext}')]
Помните, что шаблоны glob чувствительны к регистру в операционных системах с чувствительной к регистру файловой системой (Unix, Linux). В Windows glob обычно не чувствителен к регистру, что соответствует поведению самой файловой системы. ⚠️
Рекурсивный поиск и glob.iglob() для больших каталогов
Работа с большими каталогами ставит перед разработчиками две основные проблемы: как организовать рекурсивный поиск и как избежать переполнения памяти. Python 3.5+ решает первую проблему с помощью параметра recursive=True, а вторую — с помощью функции glob.iglob().
Рекурсивный поиск позволяет находить файлы не только в указанном каталоге, но и во всех его подкаталогах:
import glob
# Рекурсивный поиск всех Python-файлов
all_python_files = glob.glob('**/*.py', recursive=True)
# Рекурсивный поиск по нескольким критериям
all_data_files = glob.glob('**/*.csv', recursive=True) + glob.glob('**/*.xlsx', recursive=True)
print(f"Найдено {len(all_python_files)} Python файлов")
Для больших каталогов с тысячами файлов функция glob.glob() может потреблять слишком много памяти, так как она сразу возвращает полный список всех найденных файлов. Здесь на помощь приходит glob.iglob() — итератор, который генерирует найденные пути "на лету", один за другим, что значительно снижает потребление памяти:
# Память-эффективная обработка большого количества файлов
for python_file in glob.iglob('**/*.py', recursive=True):
with open(python_file, 'r') as f:
# Обработка файла без хранения всех путей в памяти
content = f.read()
if 'TODO' in content:
print(f"TODO найдено в {python_file}")
Преимущества glob.iglob() особенно заметны при обработке больших объемов данных, где полный список файлов может потенциально не поместиться в оперативную память. Рассмотрим более сложный пример с использованием генератора для экономии памяти:
def process_large_files():
# Создаем генератор для обработки больших файлов по одному
large_files = (
file for file in glob.iglob('**/*.csv', recursive=True)
if os.path.getsize(file) > 1024 * 1024 # Файлы больше 1 МБ
)
# Обрабатываем каждый файл по очереди
for file_path in large_files:
print(f"Обработка большого файла: {file_path}")
# Здесь код обработки файла
При работе с большими каталогами важно учитывать производительность. Вот несколько практических рекомендаций:
- Используйте более конкретные шаблоны, чтобы уменьшить количество проверяемых файлов
- Применяйте
glob.iglob()вместоglob.glob()для больших наборов данных - Ограничивайте глубину рекурсии там, где это возможно, используя более конкретные пути
- Предварительно фильтруйте каталоги, если знаете, где искать
Сравнение потребления памяти при использовании различных методов для обработки 10,000 файлов:
Мария Соколова, тренер по Python Однажды мне пришлось автоматизировать процесс обработки фотоархива, содержащего более 500,000 изображений. Моему студенту потребовалось найти все фотографии, сделанные в определенные годы и с определенными параметрами камеры (извлекаемыми из EXIF-данных).
Сначала он попытался использовать стандартный подход с
glob.glob():PythonСкопировать кодall_images = glob.glob('Photos/**/*.jpg', recursive=True) # Затем фильтрация по EXIFЭтот код аварийно завершился с ошибкой нехватки памяти, так как пытался загрузить в память полмиллиона путей к файлам одновременно.
Мы переписали код с использованием
iglob():PythonСкопировать кодfor image_path in glob.iglob('Photos/**/*.jpg', recursive=True): # Обработка каждого изображения по очереди exif_data = get_exif(image_path) if matches_criteria(exif_data): process_image(image_path)Код заработал, но обработка шла медленно — примерно 24 часа на весь архив.
Следующий шаг был критически важным. Мы заметили, что фотографии организованы по годам и месяцам в структуре
Photos/YYYY/MM/. Зная, что нужны только снимки 2018-2020 годов, мы оптимизировали шаблон:PythonСкопировать кодpatterns = [f'Photos/20{year}/**/*.jpg' for year in range(18, 21)] for pattern in patterns: for image_path in glob.iglob(pattern, recursive=True): # Более целенаправленная обработкаЭто сократило время обработки до 3 часов. Опыт показал, насколько важно не только знать инструменты Python, но и понимать, как их эффективно применять в контексте конкретной задачи.
Практические задачи: автоматизация работы с файлами
Модуль glob раскрывает свой потенциал в реальных задачах автоматизации. Рассмотрим несколько практических сценариев, где glob становится незаменимым инструментом. 🛠️
1. Пакетная обработка файлов определённого типа
import glob
import pandas as pd
import os
# Объединение нескольких CSV-файлов в один DataFrame
def merge_csv_files(directory):
all_data = []
for csv_file in glob.glob(f'{directory}/*.csv'):
df = pd.read_csv(csv_file)
df['source_file'] = os.path.basename(csv_file) # Добавляем информацию об источнике
all_data.append(df)
if all_data:
return pd.concat(all_data, ignore_index=True)
return pd.DataFrame()
# Использование функции
combined_data = merge_csv_files('data/sales')
print(f"Объединено {len(combined_data)} строк из разных CSV-файлов")
2. Очистка временных файлов
import glob
import os
import time
def cleanup_temp_files(directory, days_old=7):
"""Удаляет временные файлы старше указанного количества дней"""
current_time = time.time()
deleted_count = 0
# Ищем все временные файлы
temp_patterns = [f'{directory}/**/*.tmp', f'{directory}/**/*.temp', f'{directory}/**/~*']
for pattern in temp_patterns:
for temp_file in glob.glob(pattern, recursive=True):
# Проверяем возраст файла
file_age_days = (current_time – os.path.getmtime(temp_file)) / (60*60*24)
if file_age_days > days_old:
try:
os.remove(temp_file)
deleted_count += 1
print(f"Удалён: {temp_file}")
except Exception as e:
print(f"Ошибка при удалении {temp_file}: {e}")
return deleted_count
# Использование
removed = cleanup_temp_files('/path/to/project')
print(f"Удалено {removed} временных файлов")
3. Автоматическая организация файлов по типам
import glob
import os
import shutil
def organize_files_by_type(source_dir):
"""Организует файлы в подкаталоги по их типу"""
# Словарь соответствия расширений и папок
extensions_map = {
'documents': ['doc', 'docx', 'pdf', 'txt', 'rtf'],
'images': ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff'],
'audio': ['mp3', 'wav', 'ogg', 'flac'],
'video': ['mp4', 'avi', 'mkv', 'mov', 'wmv'],
'code': ['py', 'js', 'html', 'css', 'java', 'cpp']
}
# Создаем каталоги, если они не существуют
for folder in extensions_map:
os.makedirs(os.path.join(source_dir, folder), exist_ok=True)
# Перемещаем файлы
moved_files = 0
for file_path in glob.glob(f'{source_dir}/*.*'):
# Пропускаем каталоги
if os.path.isdir(file_path):
continue
# Получаем расширение файла без точки
ext = os.path.splitext(file_path)[1][1:].lower()
# Определяем, в какую папку переместить файл
target_folder = None
for folder, extensions in extensions_map.items():
if ext in extensions:
target_folder = folder
break
if target_folder:
filename = os.path.basename(file_path)
destination = os.path.join(source_dir, target_folder, filename)
# Проверяем, существует ли файл с таким именем
if os.path.exists(destination):
name, ext = os.path.splitext(filename)
destination = os.path.join(source_dir, target_folder, f"{name}_copy{ext}")
shutil.move(file_path, destination)
moved_files += 1
return moved_files
# Использование
count = organize_files_by_type('/path/to/downloads')
print(f"Организовано {count} файлов")
4. Мониторинг изменений в каталоге
Создадим простую систему мониторинга, которая отслеживает появление новых файлов определенного типа и выполняет действия с ними:
import glob
import time
import os
import hashlib
def monitor_directory(directory, pattern, interval=60):
"""Мониторит директорию на появление новых файлов, соответствующих шаблону"""
known_files = {}
print(f"Начало мониторинга {directory} для файлов {pattern}")
print(f"Проверка каждые {interval} секунд")
try:
while True:
current_files = {}
# Сканируем файлы, соответствующие шаблону
for file_path in glob.glob(os.path.join(directory, pattern)):
# Вычисляем хеш файла для отслеживания изменений
with open(file_path, 'rb') as f:
file_hash = hashlib.md5(f.read()).hexdigest()
current_files[file_path] = file_hash
# Проверяем новые файлы
for file_path, file_hash in current_files.items():
if file_path not in known_files:
print(f"Обнаружен новый файл: {file_path}")
process_new_file(file_path) # Обработка нового файла
elif known_files[file_path] != file_hash:
print(f"Файл изменен: {file_path}")
process_changed_file(file_path) # Обработка измененного файла
# Проверяем удаленные файлы
for file_path in list(known_files.keys()):
if file_path not in current_files:
print(f"Файл удален: {file_path}")
# Обновляем список известных файлов
known_files = current_files
# Пауза перед следующей проверкой
time.sleep(interval)
except KeyboardInterrupt:
print("Мониторинг остановлен")
def process_new_file(file_path):
"""Обрабатывает новый файл"""
print(f"Обработка нового файла: {file_path}")
# Здесь код обработки нового файла
def process_changed_file(file_path):
"""Обрабатывает измененный файл"""
print(f"Обработка измененного файла: {file_path}")
# Здесь код обработки измененного файла
# Использование
# monitor_directory('/path/to/watch', '*.pdf', 30) # Проверка каждые 30 секунд
Применение glob в задачах автоматизации существенно упрощает код и делает его более читаемым. Комбинируя glob с другими библиотеками Python, можно создавать мощные инструменты для работы с файловой системой, значительно сокращающие время на рутинные операции.
Грамотное использование модуля glob значительно упрощает работу с файловой системой в Python. Благодаря его лаконичному синтаксису и гибким возможностям поиска по шаблонам, вы можете писать более элегантный и поддерживаемый код. Масштабируйте свои решения от простого поиска файлов до сложных систем автоматизации, используя рекурсивный поиск для глубоких каталогов и итераторы для эффективной работы с большими объемами данных. Модуль glob превращает сложные задачи управления файлами в изящные однострочники, экономя ваше время и усилия. Пишите меньше кода, делайте больше работы — вот истинная философия Python в действии.