Как средствами Python перечислить файлы в директории

Раздел: Стандартная библиотека Python -> OS

Способы получения списка файлов в 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']

Получение списка файлов в Python - comments

En
Python получить список файлов (python)