2012-07-12 2 views
4

Хорошо, что у меня возникают проблемы не только с самой проблемой, но даже с попыткой объяснить мой вопрос. У меня есть дерево каталогов, состоящее из приблизительно 7 итераций, так: rootdir/a/b/c/d/e/f/destinationdirPython Glob.glob: подстановочный знак для количества каталогов между корнем и местом назначения

Дело в том, некоторые из них могут иметь 5 уровней подкаталогов и некоторые из них могут иметь столько, сколько десять, таких как:

rootdir/a/b/c/d/destinationdir 

или:

rootdir/a/b/c/d/e/f/g/h/destinationdir

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

for path in glob.glob('/rootdir/*/*/*/*/*/*/destinationdir'):
--- os.system('cd {0}; do whatever'.format(path))

Однако это работает только для каталогов с этим точным числом промежуточных подкаталогов. Есть ли способ для меня не указывать это число subdirectories(asterices); другими словами, если функция прибывает в destinationdir независимо от количества промежуточных подкаталогов и позволяет мне проходить через них. Большое спасибо!

ответ

4

Я думаю, что это можно было бы сделать более легко с os.walk:

def find_files(root,filename): 
    for directory,subdirs,files in os.walk(root): 
     if filename in files: 
      yield os.join(root,directory,filename) 

Конечно, это не позволяет вам иметь выражение Глоб в имени файла часть, но вы можете проверить, что материал с помощью регулярных выражений или fnmatch.

EDIT

Или найти каталог:

def find_files(root,d): 
    for directory,subdirs,files in os.walk(root): 
     if d in subdirs: 
      yield os.join(root,directory,d) 
1

Вы можете создать шаблон для каждого уровня отступа (увеличение 10 при необходимости):

for i in xrange(10): 
    pattern = '/rootdir/' + ('*/' * i) + 'destinationdir' 
    for path in glob.glob(pattern): 
     os.system('cd {0}; do whatever'.format(path)) 

Это будет перебирать:

'/rootdir/destinationdir' 
'/rootdir/*/destinationdir' 
'/rootdir/*/*/destinationdir' 
'/rootdir/*/*/*/destinationdir' 
'/rootdir/*/*/*/*/destinationdir' 
'/rootdir/*/*/*/*/*/destinationdir' 
'/rootdir/*/*/*/*/*/*/destinationdir' 
'/rootdir/*/*/*/*/*/*/*/destinationdir' 
'/rootdir/*/*/*/*/*/*/*/*/destinationdir' 
'/rootdir/*/*/*/*/*/*/*/*/*/destinationdir' 

Если вы должны перебрать каталоги с произвольной глубиной то я предлагаю разделить алгоритм на два этапа: один этап, где вы исследуете, где находятся все каталоги «destinationdir», и второй этап, в котором вы выполняете свои операции.

1

Это намного проще выполнить с помощью более универсального инструмента, такого как команда find (ваш вызов os.system указывает, что вы используете unix-подобную систему, поэтому это будет работать).

os.system('find /rootdir -mindepth 5 -maxdepth 10 -type d -name destinationdir | while read d; do (cd $d && do whatever;); done') 

..Note, что если вы собираетесь поместить любой предоставленный пользователем строку в этой команде, это становится резко небезопасным, и вы должны использовать subprocess.Popen вместо выполнения оболочки и разделив аргументы сами. Это безопасно, как показано на рисунке.

2

Если вы ищете файлы, вы можете использовать Formic package (раскрытие: я написал) - это реализует Apache Ant в FileSet Globs с подстановочным знаком «**»:

import formic 
fileset = formic.FileSet(include="rootdir/**/destinationdir/*") 

for file_name in fileset: 
    # Do something with file_name