Сопоставление шаблонов имен файлов с помощью модуля Python glob

Что такое модуль Python glob? Для каких типов приложений Python его можно использовать?

Модуль Python glob используется для поиска путей, соответствующих определенному шаблону. Общий термин «glob» используется для описания методов сопоставления определенных шаблонов в соответствии с правилами оболочки Unix. С помощью glob вы также можете использовать подстановочные знаки («*,?, [диапазоны]) помимо точного поиска по строке, чтобы сделать поиск пути более эффективным.

Давайте изучим модуль Python glob!

Что такое модуль Python glob?

Модуль Python glob позволяет производить поиск по именам путей для поиска файлов, соответствующих заданному шаблону (который вы определяете). Правила, установленные оболочкой Unix, используются для определения предоставленного шаблона для сопоставления файлов.

Все пути к файлам, соответствующие определенному шаблону, возвращаются с помощью функции glob модуля glob. Мы можем использовать glob для поиска определенного шаблона файла или, что, возможно, более эффективно, мы можем использовать подстановочные знаки для поиска файлов, имена которых соответствуют заданному шаблону.

Чтобы использовать glob, нам нужно импортировать его с помощью оператора import Python, как показано ниже.

import glob

Примечание: glob — это встроенный модуль, который поставляется с Python, поэтому вам не нужно устанавливать его отдельно от вашей установки Python (например, с помощью pip или conda) перед импортом.

После импорта модуля glob мы можем использовать его для поиска файлов, соответствующих определенному шаблону на нашей локальной машине.

Следующий фрагмент кода сопоставляет определенное имя файла в каталоге /opt/app/tutorial/ и отображает его в выходных данных.

import glob

file = glob.glob("/opt/app/tutorial/file1.txt")
print(file)

Вывод:

['/opt/app/tutorial/file1.txt']

В приведенном выше коде мы ищем только один текстовый файл, мы также можем искать несколько файлов с одинаковым расширением.

import glob

files = glob.glob("/opt/app/tutorial/*.txt")
print(files)

Как вы видите, мы указали «*.txt», что соответствует всем файлам с расширением txt в указанном каталоге. Символ «*» является подстановочным знаком.

Предположим, что в каталоге /opt/app/tutorial/ у нас есть следующие пять текстовых файлов:

файл1.txt
файл2.txt
файл3.txt
файл4.txt
файл5.txt

После выполнения кода Python я получаю следующий вывод:

['/opt/app/tutorial/file2.txt', '/opt/app/tutorial/file3.txt', '/opt/app/tutorial/file1.txt', '/opt/app/tutorial/file4.txt', '/opt/app/tutorial/file5.txt']

Функция glob.glob() возвращает список всех файлов, соответствующих указанному нами пути.

Вы также можете видеть, что…

Функция glob() модуля Python glob возвращает результаты в произвольном порядке.

Использование абсолютных и относительных путей с помощью Python glob

Путь, который мы указываем для функции glob(), может быть абсолютным или относительным.

Давайте посмотрим, что это значит…

  • Абсолютный путь: это полный путь к файлу от корня файловой системы.
  • Относительный путь: это путь относительно текущего каталога.

Два фрагмента кода, которые мы видели ранее, используют абсолютный путь.

Теперь давайте рассмотрим пример использования относительного пути…

import glob
 
files = glob.glob("*.txt")
print(files)

Путь, указанный в этом фрагменте кода, является относительным и относится к текущему каталогу.

Из вывода видно, что список файлов содержит только имена файлов, а не полный путь к каждому файлу:

['file2.txt', 'file3.txt', 'file1.txt', 'file4.txt', 'file5.txt']

Как использовать glob для рекурсивного поиска файлов

Слово рекурсивный означает повторение, которое относится к повторному применению правила. Мы также можем использовать glob для рекурсивного поиска файлов, что означает поиск файлов в подкаталогах.

Рекурсивная природа модуля glob полезна, поскольку вы можете не знать точное местоположение искомых файлов.

Чтобы включить рекурсивное поведение, необходимо передать рекурсивный логический аргумент в функцию glob(), установленную в True. По умолчанию этот аргумент имеет значение False.

Прежде чем использовать рекурсивный аргумент, нам нужно понять поведение подстановочного знака «двойная звездочка» (**) при использовании с функцией glob.glob().

Создайте каталог с именем test_dir в текущем каталоге, а затем внутри test_dir создайте файл с именем file6.txt. Наша структура каталогов становится следующей:

файл1.txt
файл2.txt
файл3.txt
файл4.txt
файл5.txt
test_dir/file6.txt

Теперь выполните предыдущий код Python, который использует «*.txt» как выражение имени пути. Вывод будет следующим:

['file2.txt', 'file3.txt', 'file1.txt', 'file4.txt', 'file5.txt']

Теперь передайте рекурсивный аргумент в функцию glob:

import glob

files = glob.glob("*.txt", recursive=True)
print(files)

При выполнении кода вы заметите, что вывод не меняется. Это потому, что рекурсивный аргумент должен использоваться вместе с подстановочным знаком двойной звездочки (**).

Обновите выражение, переданное функции glob(), как показано ниже (не меняйте ничего в предыдущем коде):

files = glob.glob("**/*.txt", recursive=True)

На этот раз в выводе вы также увидите «test_dir/file6.txt». Наш код сопоставил файлы.txt в текущем каталоге, а также файл.txt в подкаталоге test_dir.

['file2.txt', 'file3.txt', 'file1.txt', 'file4.txt', 'file5.txt', 'test_dir/file6.txt']

Теперь попробуем установить recursive в значение False, не меняя выражение имени пути:

files = glob.glob("**/*.txt", recursive=False)

Вывод:

['test_dir/file6.txt']

Наш код сопоставил только файл в подкаталоге.

Теперь вы знаете, как работает двойная звездочка вместе с рекурсивным параметром при использовании функции glob().

Использование подстановочных знаков с glob

С модулем glob вы можете использовать подстановочные знаки. Существует много подстановочных знаков, но наиболее используемые подстановочные знаки описаны ниже.

Звездочка (*): glob использует звездочку (*), также известную как звездочка, для сопоставления нуля или более символов.

filepath = "*.txt"
filepath = "*.py"
filepath = "*.jpg"

В приведенных выше примерах * будет соответствовать всем файлам с указанным расширением.

Двойная звездочка (**): две звездочки (**) — то же самое, что и одна звездочка, но они работают с подпапками. Когда вы ищете рекурсивно, используйте двойную звездочку (**) для поиска файлов в текущих папках, а также в подпапках.

filepath = "docs/**/*.txt"
filepath = "python/**/*.py"
filepath = "images/**/*.jpg"

Квадратные скобки ([ ]): квадратные скобки являются очень мощным подстановочным символом, поскольку они позволяют искать файлы, используя различные комбинации символов.

Например:

  • Допустим, вы хотите найти файлы, имена которых соответствуют строчным гласным буквам. Для этого вам нужно указать все строчные гласные буквы в квадратных скобках: [aeiou].
  • [0-9]: Если вы хотите сопоставить любые цифры, укажите цифры от 0 до 9 в квадратных скобках.
  • [AZ]: соответствует любым заглавным буквам, [az] соответствует любым строчным буквам. Вы также можете комбинировать заглавные и строчные буквы следующим образом: [az,AZ].
  • Если вы хотите исключить определенные символы, то вы можете использовать квадратные скобки, а также указать символ (!). Например: [!abc].

Давайте рассмотрим несколько практических примеров, чтобы понять подстановочные знаки.

Мы уже видели ранее, как работают подстановочные знаки * и **. Теперь давайте рассмотрим пример с квадратными скобками ([ ]).

В квадратных скобках мы указываем последовательность цифр или букв для поиска:

import glob

path1 = "[a-e]*.txt"
print('Files with a name that starts with a letter between a and e in the current directory')
print(glob.glob(path1))

path2 = "[1-5]*.txt"
print('Files with a name that starts with a number between 1 and 5 in the current directory')
print(glob.glob(path2))

Создайте следующие файлы в текущем каталоге, чтобы убедиться, что подстановочные выражения работают так, как и ожидалось:

a.txt
ask.txt
cat.txt
d.txt
echo.txt
delta.txt
fox.txt
1.txt
134.txt
345.txt
67.txt

А теперь выполните код.

Вывод:

Files with a name that starts with a letter between a and e in the current directory
['echo.txt', 'ask.txt', 'a.txt', 'd.txt', 'delta.txt', 'cat.txt']
Files with a name that starts with a number between 1 and 5 in the current directory
['345.txt', '1.txt', '134.txt']

Наш код работает так, как и ожидалось, а файлы «fox.txt» и «67.txt» не совпадают.

Почему следует использовать iglob, а не glob в Python?

До сих пор мы использовали функцию glob(). В модуле glob есть еще одна функция, называемая iglob().

Функция iglob() похожа на функцию glob(), главное отличие состоит в том, что iglob() возвращает генератор, который выдает имена файлов, соответствующие заданному шаблону.

Давайте подтвердим тип объекта, возвращаемого функцией iglob(), используя один из предыдущих примеров кода. Мы просто заменим функцию glob на функцию iglob.

import glob

files = glob.iglob("*.txt")
print(type(files))

[output]
<class 'generator'>

Функция glob() проходит по всем файлам и сохраняет их в памяти одновременно, в то время как iglob() возвращает генератор, который позволяет перебирать все файлы, не сохраняя их одновременно в памяти.

Передав генератор функции Python next(), вы получите обратно первое имя файла, возвращаемое функцией iglob:

print(next(files))

[output]
file2.txt

Функция iglob() очень полезна, когда мы сопоставляем большое количество файлов. Мы можем рисковать заполнить всю память, загружая их все с помощью glob().

Чтобы избежать этого, iglob() помогает нам сопоставить все имена файлов в виде генератора, что повышает производительность и сокращает использование памяти.

Чтобы вывести все файлы, соответствующие функции iglob, можно использовать цикл for в Python:

import glob

files = glob.iglob("*.txt")

for filename in files:
    print(filename)

Заключение

Теперь у вас должно быть четкое понимание того, как работает модуль glob. Вы узнали, как модуль glob особенно полезен для задач, связанных с сопоставлением шаблонов имен файлов, и как получить список всех файлов, которые соответствуют определенному шаблону.

Мы рассмотрели несколько практических примеров того, как на самом деле работает модуль glob, включая некоторые из наиболее используемых подстановочных знаков.

Вы также увидели разницу между функциями glob() и iglob() и поняли, почему следует использовать iglob() вместо функции glob().

Автор

Фото аватара

Владимир Михайлов

Программист на Python с большим количеством опыта и разнообразных проектов.