Обход всех файлов в папке Python: рекурсивное получение имен по шаблону из дерева каталогов

0
16

Краткая памятка по обходу файлов в Python

  1. Импортируйте os или pathlib в начале скрипта.
  2. Для простого обхода используйте os.listdir(‘путь’).
  3. Для быстрого обхода с метаданными используйте os.scandir(‘путь’).
  4. Для рекурсивного обхода всех подпапок используйте os.walk(‘путь’).
  5. Для современного подхода используйте pathlib.Path(‘путь’).iterdir().
  6. Для фильтрации по расширению применяйте str.endswith() или fnmatch.
  7. Для рекурсивного поиска по шаблону используйте Path.rglob(‘*.txt’).
  8. Всегда обрабатывайте PermissionError при обходе системных папок.
  9. Используйте os.path.join() для формирования полных путей.
  10. Проверяйте тип элемента через os.path.isfile() или Path.is_file().
  11. Для сложной фильтрации применяйте регулярные выражения из модуля re.
  12. Закрывайте ресурсы: при использовании os.scandir() используйте контекстный менеджер with.

(pattern, *, case_sensitive=None, recurse_symlinks=False):

Метод () возвращает список всех файлов любого типа, соответствующий заданному шаблону pattern, расположенных в каталоге, указанном в пути path.

>>> from pathlib import Path >>> paths = sorted(Path(‘.’).glob(‘*.py’)) >>> paths # [PosixPath(»), PosixPath(»), PosixPath(‘test_pathlib.py’)] # преобразуем в список строк list(map(str, paths)) # [», », ‘test_pathlib.py’] >>> path = sorted(Path(‘.’).glob(‘*/*.py’)) >>> path # [PosixPath(‘docs/’)] # что бы преобразовать объект PosixPath в строку # просто передайте его в функцию str() >>> str(path) # ‘docs/’

Шаблоны pattern те же, что и для fnmatch, с добавлением «**», что означает «этот каталог и все подкаталоги рекурсивно». Другими словами, шаблон ‘**’ указывает на рекурсивный обход каталога в глубину, указанного в пути path, и всех его подкаталогов:

ЧИТАТЬ ТАКЖЕ:  Прерывание выполнения функции в Python: остановка скрипта, команда quit и SystemExit

>>> from pathlib import Path >>> paths = sorted(Path(‘.’).glob(‘**/*.py’)) >>> paths # [PosixPath(‘build/lib/’), # PosixPath(‘docs/’), # PosixPath(»), # PosixPath(»), # PosixPath(‘test_pathlib.py’)] # преобразуем в список строк >>> list(map(str, paths)) # [‘build/lib/’, # docs/, #, # » # ‘test_pathlib.py’]

Примечание. Использование шаблона ‘**’ в больших деревьях каталогов может занять слишком много времени.

По умолчанию или когда для ключевого аргумента recurse_symlinks установлено значение False, то этот метод следует за символическими ссылками, за исключением случаев расширения подстановочных знаков **. Установите для recurse_symlinks значение True, чтобы всегда переходить по символическим ссылкам.

Изменено в Python 3.11: возвращает только каталоги, если шаблон pattern заканчивается разделителем компонентов пути (или).

Изменено в версии Python 3.12: Добавлен ключевой аргумент case_sensitivity. По умолчанию или когда аргументу case_sensitive присвоено значение None, этот метод сопоставляет пути, используя правила оформления, зависящие от конкретной платформы: как правило, с учетом регистра в POSIX и без учета регистра в Windows. Чтобы переопределить такое поведение, необходимо установить значение case_sensitive равным True или False.

Изменено в Python 3.13: аргумент pattern принимает объект, подобный пути.

Изменено в Python 3.13: Любые исключения OSError, возникающие при сканировании файловой системы, подавляются. В предыдущих версиях такие исключения подавлялись во многих случаях, но не во всех.

Часто задаваемые вопросы по обходу файлов в Python

Вопрос: Какой самый быстрый способ обойти все файлы в папке?
Ответ: os.scandir() быстрее os.listdir(), так как возвращает итератор и не загружает все имена в память сразу.

ЧИТАТЬ ТАКЖЕ:  Python sort и sorted: в чем разница и как выбрать метод сортировки

Вопрос: Как рекурсивно обойти все подпапки?
Ответ: Используйте os.walk() или Path.rglob(‘*’) для рекурсивного обхода всех директорий и файлов.

Вопрос: Как отфильтровать только файлы определенного расширения?
Ответ: Используйте str.endswith(‘.txt’) или fnmatch.filter(files, ‘*.txt’) для фильтрации по расширению.

Вопрос: В чем разница между os.listdir() и os.scandir()?
Ответ: os.listdir() возвращает только имена файлов, а os.scandir() возвращает объекты DirEntry с дополнительной информацией (тип, размер, атрибуты).

Вопрос: Как обойти файлы с помощью pathlib?
Ответ: Используйте Path.iterdir() для нерекурсивного обхода, Path.glob(‘*’) для фильтрации по шаблону и Path.rglob(‘*’) для рекурсивного обхода.

Вопрос: Как обработать ошибку доступа к папке?
Ответ: Оберните код в try-except блок с перехватом PermissionError и используйте continue для пропуска недоступных папок.

Вопрос: Можно ли использовать регулярные выражения для фильтрации файлов?
Ответ: Да, используйте модуль re с функцией re.search() или re.match() для проверки имени файла по регулярному выражению.

Вопрос: Как получить полный путь к файлу при обходе?
Ответ: Используйте os.path.join(root, file) с os.walk() или Path(file).resolve() с pathlib.

Вопрос: Как обойти только файлы, исключая папки?
Ответ: Проверяйте тип элемента: os.path.isfile(path) для os, или Path.is_file() для pathlib.

Вопрос: Как обойти файлы в папке по маске с несколькими расширениями?
Ответ: Используйте fnmatch.filter() с несколькими шаблонами или комбинируйте условия через or в list comprehension.