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
21 ответ
Использовать 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
параметр, который указывает, насколько глубокой будет рекурсия.
Не используйте os.walk.
Пример:
import os
root = "C:\\"
for item in os.listdir(root):
if os.path.isfile(os.path.join(root, item)):
print item
Я думаю, что решение на самом деле очень просто.
использование
break
чтобы сделать только первую итерацию цикла for, должен быть более элегантный способ.
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
Предложение использовать listdir
хороший Прямой ответ на ваш вопрос в Python 2: root, dirs, files = os.walk(dir_name).next()
,
Эквивалентный синтаксис Python 3 root, dirs, files = next(os.walk(dir_name))
Вы могли бы использовать os.listdir()
который возвращает список имен (для файлов и каталогов) в данном каталоге. Если вам необходимо различать файлы и каталоги, позвоните os.stat()
на каждом имени.
Если у вас есть более сложные требования, чем просто верхний каталог (например, игнорируйте каталоги VCS и т. Д.), Вы также можете изменить список каталогов, чтобы предотвратить повторное прохождение через них 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 не знает о внешней привязке.
for path, dirs, files in os.walk('.'):
print path, dirs, files
del dirs[:] # go only one level deep
Чувствовал, как бросить мои 2 пенса.
baselevel = len(rootdir.split("\\"))
for subdirs, dirs, files in os.walk(rootdir):
curlevel = len(subdirs.split("\\"))
if curlevel <= baselevel + 1:
[do stuff]
Та же идея с listdir
, но короче:
[f for f in os.listdir(root_dir) if os.path.isfile(os.path.join(root_dir, f))]
Начиная с Python 3.5 вы можете использовать os.scandir
вместо os.listdir
, Вместо строк вы получаете итератор DirEntry
объекты взамен. Из документов:
С помощью
scandir()
вместоlistdir()
может значительно повысить производительность кода, который также нуждается в типе файла или информации об атрибуте файла, потому чтоDirEntry
объекты предоставляют эту информацию, если операционная система предоставляет ее при сканировании каталога. ВсеDirEntry
методы могут выполнять системный вызов, ноis_dir()
а такжеis_file()
обычно требуется только системный вызов для символических ссылок;DirEntry.stat()
всегда требует системного вызова в Unix, но требует только одного для символических ссылок в Windows.
Вы можете получить доступ к названию объекта через DirEntry.name
который затем эквивалентен выходу os.listdir
Корневая папка изменяется для каждого каталога, который находит os.walk. Я решил эту проверку, если root == directory
def _dir_list(self, dir_name, whitelist):
outputList = []
for root, dirs, files in os.walk(dir_name):
if root == dir_name: #This only meet parent folder
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
В 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] )
Вы также можете сделать следующее:
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
Почему бы просто не использовать range
а также os.walk
в сочетании с zip
? Это не лучшее решение, но будет работать тоже.
Например, вот так:
# your part before
for count, (root, dirs, files) in zip(range(0, 1), os.walk(dir_name)):
# logic stuff
# your later part
У меня работает на питоне 3.
Также break
проще тоже между прочим (Посмотрите на ответ от @Pieter)
import os
def listFiles(self, dir_name):
names = []
for root, directory, files in os.walk(dir_name):
if root == dir_name:
for name in files:
names.append(name)
return names
Небольшое изменение в ответе Алекса, но с использованием __next__()
:
print(next(os.walk('d:/'))[2])
или же print(os.walk('d:/').__next__()[2])
с [2]
быть file
в root, dirs, file
упоминается в других ответах
Это хороший пример Python
def walk_with_depth(root_path, depth):
if depth < 0:
for root, dirs, files in os.walk(root_path):
yield [root, dirs[:], files]
return
elif depth == 0:
return
base_depth = root_path.rstrip(os.path.sep).count(os.path.sep)
for root, dirs, files in os.walk(root_path):
yield [root, dirs[:], files]
cur_depth = root.count(os.path.sep)
if base_depth + depth <= cur_depth:
del dirs[:]
Есть ловушка при использовании 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().
Вы можете использовать этот фрагмент
for root, dirs, files in os.walk(directory):
if level > 0:
# do some stuff
else:
break
level-=1
Создайте список исключений, используйте fnmatch, чтобы пропустить структуру каталогов и выполнить процесс
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**):
Вот как я это решил
if recursive:
items = os.walk(target_directory)
else:
items = [next(os.walk(target_directory))]
...