Я правильно понимаю os.walk?

Этот цикл для root, dir, файла в os.walk(startdir) работает через эти шаги?

for root in os.walk(startdir) 
    for dir in root 
        for files in dir
  1. получить root из начального каталога: C:\dir1\dir2\startdir

  2. получить папки в C:\dir1\dir2\startdir и вернуть список папок "dirlist"

  3. получить файлы в первом элементе dirlist и вернуть список файлов "filelist" в качестве первого элемента списка файловых списков.

  4. перейдите во второй элемент в dirlist и верните список файлов в этой папке "filelist2" как второй элемент списка файловых списков. и т.п.

  5. перейдите к следующему корню в папке и начните с 2. и т.д.

Правильно? Или он просто получает все корни в первую очередь, тогда все диски второго и все файлы третьи?

Ответ 1

os.walk возвращает генератор, который создает кортеж значений (current_path, каталоги в current_path, файлы в current_path).

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

Как таковой,

os.walk('C:\dir1\dir2\startdir').next()[0] # returns 'C:\dir1\dir2\startdir'
os.walk('C:\dir1\dir2\startdir').next()[1] # returns all the dirs in 'C:\dir1\dir2\startdir'
os.walk('C:\dir1\dir2\startdir').next()[2] # returns all the files in 'C:\dir1\dir2\startdir'

Так

import os.path
....
for path, directories, files in os.walk('C:\dir1\dir2\startdir'):
     if file in files:
          print 'found %s' % os.path.join(path, file)

или это

def search_file(directory = None, file = None):
    assert os.path.isdir(directory)
    for cur_path, directories, files in os.walk(directory):
        if file in files:
            return os.path.join(directory, cur_path, file)
    return None

или если вы хотите найти файл, вы можете сделать это:

import os
def search_file(directory = None, file = None):
    assert os.path.isdir(directory)
    current_path, directories, files = os.walk(directory).next()
    if file in files:
        return os.path.join(directory, file)
    elif directories == '':
        return None
    else:
        for new_directory in directories:
            result = search_file(directory = os.path.join(directory, new_directory), file = file)
            if result:
                return result
        return None

Ответ 2

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

import os.path
path=input(" enter the path\n")
for path,subdir,files in os.walk(path):
   for name in subdir:
       print os.path.join(path,name) # will print path of directories
   for name in files:    
       print os.path.join(path,name) # will print path of files

это приведет к генерации путей всех подкаталогов, файлов и файлов в подкаталогах

Ответ 3

Вот краткий пример того, как os.walk() работает вместе с некоторыми объяснениями, используя несколько функций os.

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

dirs будет содержать список каталогов чуть ниже root, а файлы будут содержать список всех файлов, найденных в этих каталогах. В следующей итерации, каждый каталог из тех, в предыдущих dirs списке будет взять на себя роль root в свою очередь, и поиск будет продолжать оттуда, спускаясь уровень только после того, как текущий уровень был поиск.

Пример кода: это будет поиск, подсчет и печать имен файлов .jpg и .gif под указанным поисковым каталогом (ваш корень). Он также использует функцию os.path.splitext(), чтобы отделить базу файла от его расширения и функцию os.path.join(), чтобы дать вам полное имя, включая путь к найденным файлам изображений.

import os

searchdir = r'C:\your_root_dir'  # your search starts in this directory (your root) 

count = 0
for root, dirs, files in os.walk(searchdir):
    for name in files:
        (base, ext) = os.path.splitext(name) # split base and extension
        if ext in ('.jpg', '.gif'):          # check the extension
            count += 1
            full_name = os.path.join(root, name) # create full path
            print(full_name)

print('\ntotal number of .jpg and .gif files found: %d' % count)

Ответ 4

Пример минимального запуска

Вот как мне нравится учить вещи:

mkdir root
cd root
mkdir \
  d0 \
  d1 \
  d0/d0_d1
touch \
   f0 \
   d0/d0_f0 \
   d0/d0_f1 \
   d0/d0_d1/d0_d1_f0
tree

Выход:

.
├── d0
│   ├── d0_d1
│   │   └── d0_d1_f0
│   ├── d0_f0
│   └── d0_f1
├── d1
└── f0

main.py

#!/usr/bin/env python3
import os
for path, dirnames, filenames in os.walk('root'):
    print('{} {} {}'.format(repr(path), repr(dirnames), repr(filenames)))

Выход:

'root' ['d0', 'd1'] ['f0']
'root/d0' ['d0_d1'] ['d0_f0', 'd0_f1']
'root/d0/d0_d1' [] ['d0_d1_f0']
'root/d1' [] []

Это все проясняет:

  • path является корневым каталогом каждого шага
  • dirnames - это список базовых имен каталогов в каждом path
  • filenames - это список базовых имен файлов в каждом path

Протестировано на Ubuntu 16.04, Python 3.5.2.

Модификация dirnames изменяет рекурсию дерева

По сути, это единственное, что вы должны иметь в виду.

Например, если вы выполните следующие операции с dirnames, это повлияет на обход:

Пройдите файл или каталог

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

#!/usr/bin/env python3

import os
import sys

def walk_file_or_dir(root):
    if os.path.isfile(root):
        dirname, basename = os.path.split(root)
        yield dirname, [], [basename]
    else:
        for path, dirnames, filenames in os.walk(root):
            yield path, dirnames, filenames

for path, dirnames, filenames in walk_file_or_dir(sys.argv[1]):
    print(path, dirnames, filenames)

Ответ 5

os.walk работает немного иначе, чем выше. В основном, он возвращает кортежи (путь, каталоги, файлы). Чтобы увидеть это, попробуйте следующее:

import pprint
import os
pp=pprint.PrettyPrinter(indent=4)
for dir_tuple in os.walk("/root"):
    pp.pprint(dir_tuple)

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