2016-11-04 4 views
2

Мне нужно сканировать каталог с сотнями или ГБ данных, которые имеют структурированные части (которые я хочу отсканировать) и неструктурированные части (которые я не хочу сканировать).Критерии каталога комплекса Python os.walk

Чтение функции os.walk, я вижу, что я могу использовать набор критериев в наборе, чтобы исключать или включать определенные имена или шаблоны каталогов.

Для этого конкретного сканирования, мне нужно было бы добавить конкретные включения/исключения критериев на каждом уровне в каталоге, например:

В корневом каталоге, представьте себе есть два полезных каталогов, «Dir A» и «Dir B 'и непригодный каталог мусора «Корзина». В Dir A есть два полезных подкаталога «Subdir A1» и «Subdir A2» и не полезный каталог «SubdirA Trash», тогда в Dir B есть два полезных подкаталога Subdir B1 и Subdir B2 плюс не полезный «SubdirB Trash», подкаталог. Посмотрел бы что-то вроде этого:

Example Directory

мне нужно иметь определенный список критериев для каждого уровня, что-то вроде этого:

level1DirectoryCriteria = множество ("Dir A", "Dir B")

level2DirectoryCriteria = множество ("Subdir А1", "А2 Subdir", "Subdir В1", "Subdir В2")

Единственные способы, которые я могу сделать, это, очевидно, непитонические, используя сложный и длинный код с множеством переменных и высоким риском нестабильности. Есть ли у кого-нибудь идеи о том, как решить эту проблему? В случае успеха он может сохранить время работы кода несколько часов за раз.

ответ

2

Вы могли бы попробовать что-то вроде этого:

to_scan = {'set', 'of', 'good', 'directories'} 
for dirpath, dirnames, filenames in os.walk(root): 
    dirnames[:] = [d for d in dirnames if d in to_scan] 
    #whatever you wanted to do in this directory 

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

Редактировать: Мы можем использовать dirpath.count(os.path.sep) для определения глубины.

root_depth = root.count(os.path.sep) #subtract this from all depths to normalize root to 0 
sets_by_level = [{'root', 'level'}, {'one', 'deep'}] 
for dirpath, dirnames, filenames in os.walk(root): 
    depth = dirpath.count(os.path.sep) - root_depth 
    dirnames[:] = [d for d in dirnames if d in sets_by_level[depth]] 
    #process this directory 
+0

Это выглядит promising- я пытаюсь его и вернусь к вам. – user3535074

+1

Решение получилось из этого! – user3535074

1

Не прямой ответ относительно os.walk но только предложение: Так как вы сканирование каталогов в любом случае, и вы, очевидно, знаете, мусорные каталоги из других каталогов, вы можете также поместить пустой файл в мусорных каталогах skip_this_dir или что-то в этом роде. Когда вы перебираете каталоги и создаете список файлов, вы проверяете наличие файла skip_this_dir, что-то вроде if 'skip_this_dir' in filenames: continue; и продолжайте следующую итерацию.

Это может не включать в себя параметры os.walk, но это делает задачу программирования немного более легкой в ​​управлении, без требования написания большого количества «грязного» кода с множеством условностей и списков include/excludes. Это также упрощает повторное использование сценария, так как вам не нужно менять какой-либо код, вы просто помещаете фиктивный файл в каталоги, которые вам нужно пропустить.

+0

Это хорошая идея, но может потребоваться много времени, чтобы добавить флаг пропуска в каналы, которые я не хочу сканировать. Гораздо проще сказать, какие каналы я хочу отсканировать, и если в будущем мне нужно добавить некоторые, это относительно просто. Вы правы в том, чтобы избегать сложного кода, хотя я буду помнить ваше предложение. – user3535074

+0

Да, если у вас много каталогов для мусора, это может быть громоздким, чтобы отметить их всех. Вы также можете повернуть рассуждения, отметив, что вы хотите обработать, но я предполагаю, что вы, вероятно, также имеете большое количество каталогов, которые вам нужно обработать. – TBZ92

0

Используя root.count (os.path.sep), я смог создать конкретные инструкции о том, что включать/исключать на каждом уровне в структуре.Выглядит примерно так:

import os 

root_depth = root.count(os.path.sep) #subtract this from all depths to normalize root to 0 

directoriesToIncludedByLevel = [{"criteriaString","criteriaString","criteriaString","criteriaString"},#Level 0 
           {"criteriaString","criteriaString","criteriaString" },#Level 1 
           {},#Level 2 
           ] 

directoriesToExcludedByLevel = [{}, #Level 0 
           {}, #Level 1 
           {"criteriaString"}, #Level 2 
           ] 


for dirpath, dirnames, filenames in os.walk(root): 

    depth = dirpath.count(os.path.sep) - root_depth 

    # Here we create the dirnames path depending on whether we use the directoriesToIncludedByLevel or the directoriesToExcludedByLevel 
    if depth == 2: #Where we define which directories to exclude 
     dirnames[:] = [d for d in dirnames if d not in directoriesToExcludedByLevel[depth]] 
    elif depth < 2 : #Where we define which directories to INclude 
     dirnames[:] = [d for d in dirnames if d in directoriesToIncludedByLevel[depth]] 
0

Я искал решение, подобное OP. Мне нужно было сканировать вложенные папки и нужно было исключить любую папку с папками с надписью «trash». Моим решением было использовать метод string find(). Вот как я использовал его:

for (dirpath, dirnames, filenames) in os.walk(your_path): 
    if dirpath.find('trash') > 0: 
     pass 
    elif dirpath.find('trash)') < 0: 
     do_stuff 

Если «мусор» будет найден, то он будет возвращать номер индекса. В противном случае find() вернет -1.

Вы можете найти более подробную информацию о методе находки() здесь: https://www.tutorialspoint.com/python/string_find.htm