Теперь, когда наши файлы отсортированы и раскиданы по разным папкам , наша файловая система очень напоминает реальные условия. Заказчик, который попросил нас написать эту программу, хочет расширить функционал и хочет иметь возможность выводить на экран все файлы, которые у него хранятся в папке downloads, минуя вложенные папки. До сортировки, когда все файлы хранились в одной директории, никаких проблем не было, мы просто вызвали бы функцию os.listdir()
. Но сейчас при вызове этой функции мы увидим только список папок, а заказчик хочет видеть список всех файлов во всех папках.
Ссылка на репл если окно ниже не работает
Да здравствует Рекурсия!
Алгоритм здесь очень простой: Находясь в папке downloads, получаем список всех директорий и проходимся по ним. Если текущий элемент является файлом, выводим его на экран. Иначе если он является папкой, то нам нужно получить список всех директорий в этой папке, пройтись по ним, отслеживая кто является файлом, а кто папкой. Если это файл — выводим его на экран, иначе… ну вы поняли.
Начнём с заготовки, объявим функцию walk(dir)
, которая на вход будет принимать папку в которой необходимо получить список директорий. А если говорить научным языком : «функция walk, в параметре которой указывается абсолютный или относительный путь». Что такое абсолютный путь вы уже знаете. В двух словах — это полный адрес пути, начиная с самого первого элемента (например, диска С).
Название папки, в нашем случае, это относительный путь. Относительный путь указывается всегда от того места в котором сейчас программа активна.
Прокомментируем текущий код функции walk(). При вызове (33 строка) мы передаём ей текущий рабочий каталог (мы находимся в папке downloads). Функция получает все директории этой папки (строка 27). Распечатывает текущий элемент списка, а затем проверяет, является ли он папкой (строка 29). Если текущая директория является папкой, то мы опять вызываем функцию walk() (30 строка), куда передаём в качестве пути папку на которой мы остановились (в нашем примере это папка images) . Для данной папки опять идёт перебор всех элементов в ней.
В результате на экране мы увидим список абсолютно всех папок и файлов. И как же нам выводить на экран только файлы?
Отличить файл не так-то уж и просто!
Казалось бы, можно просто написать условие, которое определяет, что это файл и дело в шляпе! (строка 29, код ниже).
Но не всё так просто. Если вы запустите код слева, то вообще ничего на экране не появится. Дело в том, что функция isfile(name)
, пытается искать файл в текущем рабочем каталоге. И если вы распечатаете результат getcwd()
на каждой итерации, то увидите, что программа никуда из папки downloads не уходила. Не смотря на то, что функция получает список директорий вложенных папок, по факту мы же нигде не применяем метод chdir()
, который сменил бы нам текущий каталог. Именно поэтому мы продолжаем «сидеть» в downloads. Функция isfile(name)
ищет файл name именно в рабочем каталоге (downloads), а его там ,естественно, нет! Для того чтобы условие сработало необходимо передать абсолютный путь в качестве аргумента name.
Перед проверкой на файл перепишем относительный путь в переменной name на абсолютный путь. Используя функцию join(direction, name)
, мы без проблем сформируем полный путь до файла name.
Код представленный выше в 28 строке получает абсолютный путь, именно по нему мы получаем информацию о том, является ли элемент, на который указывает путь, файлом (строка 29) или папкой (строка 33). Так же, появилась строка 30. Здесь мы выполняем обратную операцию, из абсолютного пути name, получаем название файла с расширением. И выводим его на экран (строка 31).
И так, задача решена! Вы молодец! Теперь при желании, можно всегда получить список файлов который содержится в конкретной директории, минуя вложенные папки. Кстати, этот код можно смело запускать на вашем компьютере. Советуем попробовать!
На следующем уроке, мы найдём файл, который занимает больше всего места на компьютере.