Как только вы натолкнетесь на **
, вам придется пройтись по всей структуре каталогов, поэтому я думаю, что в этот момент самый простой способ - это перебрать каталог с помощью os.walk, construct путь, а затем проверьте, соответствует ли он шаблону. Вероятно, вы можете преобразовать в регулярные выражения что-то вроде:
def glob_to_regex(pat, dirsep=os.sep):
dirsep = re.escape(dirsep)
print re.escape(pat)
regex = (re.escape(pat).replace("\\*\\*"+dirsep,".*")
.replace("\\*\\*",".*")
.replace("\\*","[^%s]*" % dirsep)
.replace("\\?","[^%s]" % dirsep))
return re.compile(regex+"$")
(хотя обратите внимание, что это не так полнофункционально - например, он не поддерживает шаблоны глобусов в стиле * 1005, хотя, возможно, это можно было бы добавить). (Первое совпадение \*\*/
должно охватывать такие случаи, как \*\*/CVS
сопоставление ./CVS
, а также наличие только \*\*
для сопоставления в хвосте.)
Однако, очевидно, что вы не хотите проходить все ниже текущего dir, когда не обрабатываете паттерн **
, поэтому я думаю, что вам понадобится двухфазный подход. Я не пробовал реализовать приведенное ниже, и, возможно, есть несколько угловых случаев, но я думаю, что это должно сработать:
Разделить шаблон по разделителю каталогов. т.е. pat.split('/') -> ['**','CVS','*']
Пройдите по каталогам и посмотрите на соответствующую часть шаблона для этого уровня. то есть. n levels deep -> look at pat[n]
.
Если pat[n] == '**'
перейти на указанную выше стратегию:
- Восстановите шаблон с помощью
dirsep.join(pat[n:])
- Преобразовать в регулярное выражение с
glob\_to\_regex()
- Рекурсивно
os.walk
через текущий каталог, создавая путь относительно уровня, с которого вы начали. Если путь соответствует регулярному выражению, выведите его.
Если pat не соответствует "**"
, и это последний элемент в шаблоне, то вывести все файлы / каталоги, соответствующие glob.glob(os.path.join(curpath,pat[n]))
Если pat не соответствует "**"
, и это НЕ последний элемент в шаблоне, то для каждого каталога проверьте, соответствует ли он (с glob) pat[n]
. Если это так, вернитесь вниз, увеличивая глубину (чтобы она выглядела как pat[n+1]
)