Как средствами Python перечислить файлы в директории
Способы получения списка файлов в Python
Основное эффективное решение: модуль pathlib
Начиная с Python 3.4, рекомендуется использовать модуль pathlib для работы с путями файловой системы. Он предоставляет объектно-ориентированный интерфейс и хорошо справляется с получением списка содержимого директории. Метод Path.iterdir() возвращает итератор объектов Path, что позволяет экономить память при работе с большими каталогами.
from pathlib import Path
# Создаём объект пути
p = Path('.')
# Получаем список элементов в директории (итератор)
entries = p.iterdir()
# Преобразуем в список, если нужно
file_list = list(entries)
Python получить путь (получение пути к файлу в python)
Чтобы отфильтровать только файлы, используется метод is_file(). Пример с генератором списка:
files = [item for item in Path('.').iterdir() if item.is_file()]
print(files)
Python получить список файлов (получение списка файлов в python)
Результатом будет список объектов Path, представляющих файлы в текущей директории. Для получения имён в виде строк можно добавить вызов .name.
Типичные проблемы:
- FileNotFoundError – если указанный путь не существует. Проверять существование через Path.exists().
- PermissionError – при отсутствии прав на чтение директории. Обрабатывать исключение или использовать try/except.
- Сортировка – порядок элементов не определён. Для упорядочивания применить sorted().
Как получить список всех файлов и папок с помощью os.listdir?
Функция os.listdir(path) возвращает список строк с именами всех элементов указанной директории. Это самый простой и быстрый вариант, если не требуется дополнительная информация об элементах.
import os
# Список имён в текущей папке
all_items = os.listdir('.')
print(all_items)
Чтобы отличить файлы от папок, необходимо использовать os.path.isfile() или os.path.isdir(). Пример:
only_files = [f for f in os.listdir('.') if os.path.isfile(f)]
print(only_files)
Проблема: os.listdir не возвращает полные пути, поэтому при работе не с текущей директорией нужно формировать полный путь для проверок.
Как эффективно получить список файлов с атрибутами через os.scandir?
Функция os.scandir(path) возвращает итератор объектов DirEntry, которые содержат не только имя, но и кэшированные атрибуты (тип, размер, время изменения). Это быстрее, чем os.listdir + os.stat для каждого элемента.
import os
with os.scandir('.') as entries:
for entry in entries:
if entry.is_file():
print(entry.name, entry.stat().st_size)
Объект DirEntry поддерживает методы .is_file(), .is_dir(), .stat(), что упрощает фильтрацию.
Важно: os.scandir не следует использовать после завершения контекстного менеджера (with), итератор становится недействительным.
Как получить файлы, соответствующие шаблону, с помощью glob?
Если требуется список файлов с определённым расширением или именем, удобно применять модуль glob. Он поддерживает подстановочные символы (*, ?, []) и возвращает отсортированный список путей (как строк).
import glob
# Все файлы .txt в текущей папке
txt_files = glob.glob('*.txt')
print(txt_files)
Для рекурсивного поиска по поддиректориям используется параметр recursive=True и шаблон **/:
all_py_files = glob.glob('**/*.py', recursive=True)
print(all_py_files)
Аналог в pathlib – метод .glob() и .rglob().
Особенность: glob возвращает пути в формате ОС, на Windows – с обратными слешами. Это может привести к различиям в кроссплатформенном коде.
Как рекурсивно обойти все поддиректории с os.walk?
Функция os.walk(top) генерирует кортежи (dirpath, dirnames, filenames) для каждого каталога в дереве. Это классический способ рекурсивного обхода, работающий на всех версиях Python.
import os
for dirpath, dirnames, filenames in os.walk('.'):
for filename in filenames:
# Полный путь к файлу
full_path = os.path.join(dirpath, filename)
print(full_path)
Список папок dirnames можно модифицировать в процессе обхода, например, исключить некоторые каталоги.
Производительность: os.walk не подходит для очень глубоких деревьев из-за рекурсивного характера. Для больших объёмов лучше использовать pathlib.rglob с осторожностью.
Как применить pathlib для рекурсивного поиска?
Метод Path.rglob(pattern) рекурсивно ищет файлы и папки, соответствующие шаблону, начиная с указанного пути. Возвращает итератор объектов Path.
from pathlib import Path
# Все файлы .log рекурсивно
for log_file in Path('.').rglob('*.log'):
print(log_file)
Для получения всех файлов (без фильтрации) можно использовать Path.rglob('*').
Внимание: rglob может вернуть также и директории, если шаблон совпадает. Чтобы получить только файлы, нужно добавить проверку .is_file().
Общие проблемы и способы их решения
- Отсутствие сортировки. По умолчанию порядок не гарантируется. Используйте sorted() или библиотеку natsort для естественной сортировки.
- Большие директории. Не следует собирать весь список в память, если это не требуется. Используйте итераторы (iterdir, scandir) и обрабатывайте элементы по мере поступления.
- Проблемы с кодировкой имён. В именах файлов могут быть символы, не поддерживаемые локалью. Для корректной обработки задавайте locale или используйте bytes-пути.
- Обработка символических ссылок. Методы is_file() по умолчанию следуют ссылкам. Для проверки самой ссылки используйте is_symlink().
Расширенные примеры получения списка файлов
Ниже приведены примеры, демонстрирующие нестандартные сценарии и тонкую настройку поиска файлов.
Фильтрация по дате изменения (pathlib)
from pathlib import Path
from datetime import datetime, timedelta
# Файлы, изменённые за последние 7 дней
deadline = datetime.now() - timedelta(days=7)
recent_files = [f for f in Path('.').iterdir() if f.is_file() and datetime.fromtimestamp(f.stat().st_mtime) > deadline]
for f in recent_files:
print(f.name)
file1.txt report.docx
Фильтрация по размеру (os.scandir)
import os
# Файлы размером более 1 МБ
with os.scandir('.') as entries:
for entry in entries:
if entry.is_file() and entry.stat().st_size > 1024*1024:
print(f'{entry.name}: {entry.stat().st_size} bytes')
bigfile.mp4: 1536000 bytes
Рекурсивный обход с игнорированием .git папки (os.walk)
import os
for dirpath, dirnames, filenames in os.walk('.'):
# Исключаем папку .git
if '.git' in dirnames:
dirnames.remove('.git')
for filename in filenames:
if filename.endswith('.py'):
print(os.path.join(dirpath, filename))
./src/main.py ./tests/test.py
Работа с символическими ссылками (pathlib)
from pathlib import Path
# Получить только символические ссылки
links = [p for p in Path('.').iterdir() if p.is_symlink()]
for link in links:
target = link.resolve() # разрешить путь
print(f'{link.name} -> {target}')
mylink -> /home/user/real_file.txt
Получение списка файлов с абсолютными путями
from pathlib import Path
# Используем .resolve() или .absolute()
abs_files = [f.resolve() for f in Path('.').iterdir() if f.is_file()]
print(abs_files[:3])
[WindowsPath('C:/Users/user/project/file1.txt'), WindowsPath('C:/Users/user/project/config.yml')]
Кроссплатформенный glob с нормализацией пути
import glob
import os
# Получить все .png файлы и привести пути к POSIX-виду (прямые слеши)
png_files = [f.replace(os.sep, '/') for f in glob.glob('**/*.png', recursive=True)]
print(png_files)
['images/photo1.png', 'images/photo2.png']