glob Python
Введение | |
Пример | |
Поиск по шаблону | |
Поиск по нескольким директориям | |
Поиск по вложенным директориям | |
Поиск скрытых файлов | |
iglob | |
Похожие статьи |
Введение
В этой статье вы узнаете как работать с несколькими файлами одновременно с помощью glob.
Модуль glob находит все имена путей, соответствующие указанному шаблону, в соответствии с правилами,
используемыми оболочкой
Unix
, хотя результаты возвращаются в произвольном порядке.
Расширение тильдой не выполняется, но *, ? и диапазоны символов, выраженные с помощью [], будут правильно сопоставлены.
Это делается с помощью функций os.scandir() и fnmatch.fnmatch() совместно, а не путем фактического вызова подоболочки.
Оффициальная документация
Пример
Предположим, что мы находимся в директории glob_ex:
glob_ex/ └── sample_files ├── it.txt ├── testing.txt └── travel.txt
# glob_ex.py import glob files = glob.glob("./sample_files/*.txt") print(files)
python glob_ex.py
['./sample_files/it.txt', './sample_files/travel.txt']
Поиск по шаблону
Примеры других шаблонов для поиска
… files = glob.glob("./sample_files/?.txt") print(files) files = glob.glob("./sample_files/??.txt") print(files) files = glob.glob("./sample_files/t*.txt") print(files)
['./sample_files/it.txt'] ['./sample_files/it.txt'] ['./sample_files/testing.txt', './sample_files/travel.txt']
… # starts with character from the range files = glob.glob("./sample_files/[it]*.txt") print(files) files = glob.glob("./sample_files/[ghi]*.txt") print(files) files = glob.glob("./sample_files/[rst]*.txt") print(files) files = glob.glob("./sample_files/[abc]*.txt") print(files)
['./sample_files/it.txt', './sample_files/testing.txt', './sample_files/travel.txt'] ['./sample_files/it.txt'] ['./sample_files/testing.txt', './sample_files/travel.txt'] []
… # starts with character not from the range files = glob.glob("./sample_files/[!i]*.txt") print(files) files = glob.glob("./sample_files/[!t]*.txt") print(files) files = glob.glob("./sample_files/[!abc]*.txt") print(files)
['./sample_files/testing.txt', './sample_files/travel.txt'] ['./sample_files/it.txt'] ['./sample_files/it.txt', './sample_files/testing.txt', './sample_files/travel.txt']
# glob_ex.py import glob files = glob.glob("./sample_files/*.txt") for file in files: print(file) with open(file, "r") as f: lines = f.readlines() for line in lines: print(line, end = "")
python glob_ex.py
./sample_files/it.txt beget.com kaspersky.com ./sample_files/testing.txt www.eth1.ru www.otus.ru ./sample_files/travel.txt aviasales.com booking.com
Поиск по нескольким директориям
Обновим структуру проекта
glob_ex/ ├── glob_ex.py ├── heihei │ ├── Finland.html │ ├── Spain.html │ └── Sweden.html └── topbicycle ├── forward.html ├── stark.html └── stels.html
Чтобы искать сразу в нескольких директориях внутри корневой нужно использовать **.
Если версия вашего Python 3.10 или выше рекомендую указать
корневую директорию с помощью root_dir
import glob files = glob.glob("**/*.html", root_dir="/mnt/c/Users/Andrei/glob_ex/" ) print(files)
['heihei/Finland.html', 'heihei/Spain.html', 'heihei/Sweden.html', 'topbicycle/forward.html', 'topbicycle/stark.html', 'topbicycle/stels.html']
root_dir нужно указывать в соответсвии с окружением в котором запускается Python.
В данном примере Python запущен в
WSL2
, поэтому перед /c указан /mnt.
/mnt/c/Users/Andrei/glob_ex/
В Git Bash путь будет начинаться сразу с /
/c/Users/Andrei/glob_ex/
В полноценном Linux скорее всего с /home
/home/andrei/glob_ex/
В Windows , например, в PowerShell этот же путь будет выглядеть как
C:\Users\Andrei\glob_ex
Поиск по вложенным директориям
Усложним структуру проекта, добавив вложенные директории
glob_ex/ ├── glob_ex.py ├── heihei │ ├── Armenia │ │ ├── .hidden.html │ │ ├── holidays │ │ │ ├── easter.html │ │ │ └── sargis.html │ │ └── index.html │ ├── Finland.html │ ├── Spain.html │ └── Sweden.html └── topbicycle ├── forward.html ├── stark.html └── stels.html
Если теперь запустить тот же скрипт он не найдёт файлы в новой поддиректории Armenia.
['heihei/Finland.html', 'heihei/Spain.html', 'heihei/Sweden.html', 'topbicycle/forward.html', 'topbicycle/stark.html', 'topbicycle/stels.html']
Параметр recursive регулирует поиск во вложенных директориях. Если установить recursive=True то поиск будет осуществляться по всем поддиректориям.
import glob files = glob.glob("**/*.html", root_dir="/mnt/c/Users/Andrei/glob_ex/", recursive=True ) print(files)
['heihei/Finland.html', 'heihei/Spain.html', 'heihei/Sweden.html', 'heihei/Armenia/index.html', 'heihei/Armenia/holidays/easter.html', 'heihei/Armenia/holidays/sargis.html', 'topbicycle/forward.html', 'topbicycle/stark.html', 'topbicycle/stels.html']
Теперь скрипт находит все файлы из поддиректории Armenia, соответствующие шаблону.
Поиск скрытых файлов
Если у вас Python версии 3.11 и выше, то можно использовать опцию include_hidden,
с помощью которой в директории Armenia можно найти файл
.hidden.html
Напоминаю, что новую структуру проекта можно изучить
здесь
О том как установить свежую версию Python в
Linux
или
WSL
вы можете прочитать в статье
«Установка Python в Linux»
import glob files = glob.glob("**/*.html", root_dir="/mnt/c/Users/Andrei/glob_ex/", recursive=True, include_hidden=True ) print(files)
['heihei/Finland.html', 'heihei/Spain.html', 'heihei/Sweden.html', 'heihei/Armenia/.hidden.html', 'heihei/Armenia/index.html', 'heihei/Armenia/holidays/easter.html', 'heihei/Armenia/holidays/sargis.html', 'topbicycle/forward.html', 'topbicycle/stark.html', 'topbicycle/stels.html']
Со всеми этими опциями можно применять те же самые шаблоны, что и раньше.
import glob files = glob.glob("**/[st]*.html", root_dir="/mnt/c/Users/Andrei/glob_ex/", recursive=True, include_hidden=True ) print(files)
['heihei/Armenia/holidays/sargis.html', 'topbicycle/stark.html', 'topbicycle/stels.html']
import glob files = glob.glob("**/[St]*.html", root_dir="/mnt/c/Users/Andrei/glob_ex/", recursive=True, include_hidden=True ) print(files)
['heihei/Spain.html', 'heihei/Sweden.html']
iglob
Для работы с большими объемами данных может пригодится метод iglob, который возвращает итератор
import glob globs = glob.iglob("**/*.html", root_dir="/mnt/c/Users/Andrei/glob_ex/", recursive=True, include_hidden=True ) print(globs) print("type(globs): ", type(globs)) print("globs.__next__: ", globs.__next__) print("type(globs.__next__): ", type(globs.__next__)) print(globs.__next__()) print(globs.__next__()) # another way to call next() print(next(globs)) print(next(globs))
<itertools.chain object at 0x7fce30e36ad0> type(globs): <class 'itertools.chain'> globs.__next__: <method-wrapper '__next__' of itertools.chain object at 0x7fce30e36ad0> type(globs.__next__): <class 'method-wrapper'> heihei/Finland.html heihei/Spain.html heihei/Sweden.html heihei/Armenia/.hidden.html
Обойти все файлы можно с помощью
цикла for
Найдём все .py файлы в директории python. Для большей наглядности вывода используем функцию
enumerate()
import glob globs = glob.iglob("**/*.py", root_dir="/mnt/c/Users/Andrei/python/", recursive=True, include_hidden=True ) for i, file in enumerate(globs, 2): print(i, file, sep=': ')
2: copy_ex.py 3: dict_ex.py 4: dir_ex.py 5: pass_arg.py 6: random_gen.py 7: random_gen2.py 8: tcompl_ex.py 9: glob_ex/glob_ex.py 10: glob_ex/glob_ex1.py 11: glob_ex/glob_ex3.py 12: glob_ex/iglob_ex.py 13: Python-3.11.3/python-config.py 14: Python-3.11.3/python.exe-gdb.py 15: Python-3.11.3/setup.py 16: Python-3.11.3/build/lib.linux-x86_64-3.11/_sysconfigdata__linux_x86_64-linux-gnu.py 17: Python-3.11.3/Doc/conf.py … 2934: venv/Lib/site-packages/setuptools/_vendor/tomli/__init__.py 2935: venv/Lib/site-packages/_distutils_hack/override.py 2936: venv/Lib/site-packages/_distutils_hack/__init__.py