2008-10-23 2 views
70

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

def _dir_list(self, dir_name, whitelist): 
    outputList = [] 
    for root, dirs, files in os.walk(dir_name): 
     for f in files: 
      if os.path.splitext(f)[1] in whitelist: 
       outputList.append(os.path.join(root, f)) 
      else: 
       self._email_to_("ignore") 
    return outputList 
+0

Другой случай, когда множество возможных подходов и всех предостережений, которые идут с ними показывает, что эта функция должна быть добавлена ​​в Python стандартная библиотека. – antred 2016-10-31 19:26:09

ответ

74

Используйте функцию walklevel.

import os 

def walklevel(some_dir, level=1): 
    some_dir = some_dir.rstrip(os.path.sep) 
    assert os.path.isdir(some_dir) 
    num_sep = some_dir.count(os.path.sep) 
    for root, dirs, files in os.walk(some_dir): 
     yield root, dirs, files 
     num_sep_this = root.count(os.path.sep) 
     if num_sep + level <= num_sep_this: 
      del dirs[:] 

Он работает так же, как os.walk, но вы можете передать ему параметр level, который указывает, насколько глубоко рекурсии будет идти.

+1

Эта функция фактически «идет» по всей структуре, а затем удаляет записи ниже определенной точки? Или что-то более умное происходит? Я даже не уверен, как это проверить с помощью кода. --python beginner – mathtick 2010-08-19 18:05:48

6

Вы можете использовать os.listdir(), который возвращает список имен (для обоих файлов и каталогов) в заданной директории. Если вам нужно различать файлы и каталоги, вызовите os.stat() по каждому имени.

154

Не используйте os.walk.

Пример:

import os 

root = "C:\\" 
for item in os.listdir(root): 
    if os.path.isfile(os.path.join(root, item)): 
     print item 
+5

это должен был быть принятый ответ ... – 576i 2016-05-19 12:29:24

+1

@ 576i: это не отличает файлы и каталоги – Olexandr 2016-06-03 09:07:29

+0

@Alexandr `os.path.isfile` и` os.path.isdir` позволяет вам различать. Я не понимаю, так как `os.path.isfile` находится в образце кода с '08, а ваш комментарий - от '16. Это, безусловно, лучший ответ, поскольку вы не собираетесь ходить по каталогу, но перечислите его. – 2017-08-29 08:17:38

14

Предложение использовать listdir является хорошим. Прямой ответ на ваш вопрос: root, dirs, files = os.walk(dir_name).next()

+0

О, я получал от этого какую-то смешную ошибку. ValueError: слишком много значений для распаковки – Setori 2008-10-24 01:34:27

+0

Nice! Похоже, как взломать. Например, когда вы включаете двигатель, но разрешаете ему совершить один оборот, а затем потяните ключ, чтобы он умер. – 2017-08-29 08:24:12

8

Если у вас есть более сложные требования, чем только верхний каталог (например, игнорировать VCS-dirs и т. Д.), Вы также можете изменить список каталогов, чтобы предотвратить их повторение через os.walk.

т.е.

def _dir_list(self, dir_name, whitelist): 
    outputList = [] 
    for root, dirs, files in os.walk(dir_name): 
     dirs[:] = [d for d in dirs if is_good(d)] 
     for f in files: 
      do_stuff() 

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

+1

точка для указания необходимости мутирования! – darKoram 2012-11-20 22:43:11

1

Вы также можете сделать следующее:

for path, subdirs, files in os.walk(dir_name): 
    for name in files: 
     if path == ".": #this will filter the files in the current directory 
      #code here 
22

Я думаю, что решение на самом деле очень просто.

использование

break 

только сделать первую итерацию цикла, должна быть более изящным способом.

for root, dirs, files in os.walk(dir_name): 
    for f in files: 
     ... 
     ... 
    break 
... 

Первый раз, когда вы звоните os.walk, она возвращает тюльпаны для текущего каталога, а затем на следующем цикле содержимое следующего каталога.

Возьмите оригинальный сценарий и просто добавьте перерыв.

def _dir_list(self, dir_name, whitelist): 
    outputList = [] 
    for root, dirs, files in os.walk(dir_name): 
     for f in files: 
      if os.path.splitext(f)[1] in whitelist: 
       outputList.append(os.path.join(root, f)) 
      else: 
       self._email_to_("ignore") 
     break 
    return outputList 
4

Та же идея с listdir, но короче:

[f for f in os.listdir(root_dir) if os.path.isfile(os.path.join(root_dir, f))] 
0

Это, как я решил, что

if recursive: 
    items = os.walk(target_directory) 
else: 
    items = [next(os.walk(target_directory))] 

... 
0

Существует поймать при использовании listdir. Os.path.isdir (идентификатор) должен быть абсолютным путем.Для того, чтобы подобрать подкаталоги вы делаете:

for dirname in os.listdir(rootdir): 
    if os.path.isdir(os.path.join(rootdir, dirname)): 
    print("I got a subdirectory: %s" % dirname) 

Альтернативой является изменение в каталог, чтобы сделать тестирование без os.path.join().

2

В Python 3, я был в состоянии сделать это:.

import os 
dir = "/path/to/files/" 

#List all files immediately under this folder: 
print (next(os.walk(dir))[2]) 

#List all folders immediately under this folder: 
print (next(os.walk(dir))[1]) 
4
for path, dirs, files in os.walk('.'): 
    print path, dirs, files 
    del dirs[:] # go only one level deep 
0

Вы можете использовать этот фрагмент

for root, dirs, files in os.walk(directory): 
    if level > 0: 
     # do some stuff 
    else: 
     break 
    level-=1 
3

Войлок как бросание моих 2 пенсов в

baselevel = len(rootdir.split("\\")) 
for subdirs, dirs, files in os.walk(rootdir): 
    curlevel = len(subdirs.split("\\")) 
    if curlevel <= baselevel + 1: 
     [do stuff] 
0

создать список исключений, использовать fnmatch, чтобы пропустить структуру каталогов d сделать процесс

excludes= ['a\*\b', 'c\d\e'] 
for root, directories, files in os.walk('Start_Folder'): 
    if not any(fnmatch.fnmatch(nf_root, pattern) for pattern in excludes): 
     for root, directories, files in os.walk(nf_root): 
      .... 
      do the process 
      .... 

же, как для «включает в себя»:

if **any**(fnmatch.fnmatch(nf_root, pattern) for pattern in **includes**): 
Смежные вопросы