Функция os.walk
Функция walk() модуля os принимает один обязательный аргумент - имя каталога.
Возвращает объект-генератор, из которого получают кортежи для каждого каталога переданной файловой иерархии.
Каждый кортеж состоит из трех элементов:
- Адрес очередного каталога в виде строки.
- В форме списка имена подкаталогов первого уровня вложенности для данного каталога.
- В виде списка имена файлов данного каталога.
Допустим, есть такое дерево каталогов:
Передадим каталог test функции os.walk():
>>> import os
>>> tree = os.walk('test')
>>> tree
<generator object walk at 0x7f1119ca0518>
>>> for i in tree:
... print(i)
...
('test', ['cgi-bin'], ['dgs.png', 'index.html'])
('test/cgi-bin', ['backup', 'another'], ['hello.py'])
('test/cgi-bin/backup', [], [])
('test/cgi-bin/another', [], ['data.txt'])
Если передать абсолютный адрес, то получится так:
>>> for i in os.walk('/home/pl/test'):
... print(i)
...
('/home/pl/test', ['cgi-bin'], ['dgs.png', 'index.html'])
('/home/pl/test/cgi-bin', ['backup', 'another'], ['hello.py'])
('/home/pl/test/cgi-bin/backup', [], [])
('/home/pl/test/cgi-bin/another', [], ['data.txt'])
Каждый кортеж включает три элемента. Первый – адрес каталога, второй – список его поддиректорий первого уровня, третий – список имен файлов. Если вложенных каталогов или файлов нет, соответствующий список пуст.
Поскольку walk() возвращает генератор, повторно извлечь из него данные не получится. Если мы еще раз запустим цикл с переменной tree
, то ничего не получим. Объект-генератор, с которым переменная была связана, уже был использован. Он выдал свое содержимое и больше его не содержит. Поэтому, чтобы сохранить кортежи для последующей многократной обработки, имеет смысл добавлять их в список:
>>> folder = []
>>> for i in os.walk('test'):
... folder.append(i)
...
>>> folder
[('test', ['cgi-bin'], ['dgs.png', 'index.html']), ('test/cgi-bin', ['backup', 'another'], ['hello.py']), ('test/cgi-bin/backup', [], []), ('test/cgi-bin/another', [], ['data.txt'])]
Теперь если потребуются полные адреса файлов можно извлекать из списка каждый кортеж, распаковывать его и соединять адрес с именем файла:
>>> for address, dirs, files in folder:
... for file in files:
... print(address+'/'+file)
...
test/dgs.png
test/index.html
test/cgi-bin/hello.py
test/cgi-bin/another/data.txt
Переменная address
на каждой итерации связывается с первым элементом очередного кортежа (строкой, содержащей адрес каталога), dirs
– со вторым элементом (списком подкаталогов), а files
- со списками файлов этого каталога. Во вложенном цикле извлекается каждый отдельный файл из списка файлов.
Можно не распаковывать кортеж, а обращаться к его элементам по индексам (0 - адрес, 1 - список каталогов, 2 - список файлов):