Я хотел бы найти файлы, полное имя которых (относительное, хотя и абсолютное тоже неплохо) соответствует заданному регулярному выражению (например, как glob
, но для совпадений регулярных выражений вместо совпадений с подстановочными знаками оболочки). Используя find
, можно было бы сделать, например:
find . -regex ./foo/\w+/bar/[0-9]+-\w+.dat
Конечно, я мог бы использовать find
через os.system (...)
или os.exec * (...)
, но я ищу решение на чистом Python. Следующий код объединяет os.walk (...)
с регулярными выражениями модуля re
- это простое решение Python (оно ненадежно и пропускает многие (не такие уж угловатые) угловые случаи, но это достаточно хорошо gh для моего одноразового использования, поиска определенных файлов данных для одноразовой вставки в базу данных.)
import os
import re
def find(regex, top='.'):
matcher = re.compile(regex)
for dirpath, dirnames, filenames in os.walk(top):
for f in filenames:
f = os.path.relpath(os.path.join(dirpath, f), top)
if matcher.match(f):
yield f
if __name__=="__main__":
top = "."
regex = "foo/\w+/bar/\d+-\w+.dat"
for f in find(regex, top):
print f
Но это неэффективно. Поддеревья, содержимое которых не может соответствовать регулярному выражению (например, ./ foo / \ w + / baz /
, чтобы продолжить пример выше), обходятся без необходимости. В идеале эти поддеревья следует обрезать с пути; любой подкаталог, путь которого не является частичным совпадением с регулярным выражением, не должен проходить. (Я предполагаю, что GNU find
реализует такую оптимизацию, но я не подтвердил это с помощью тестов или изучения исходного кода.)
Кто-нибудь знает о Python-реализации надежного find
, в идеале с оптимизацией удаления поддерева? Я надеюсь, что мне просто не хватает метода в модуле os.path
или в каком-либо стороннем модуле.