Рубріки: ОсновыТеория

Функция walk() модуля OS в Python

Сергій Бондаренко

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

Назначение функции os.walk()

Модуль OS в Python часто используется для взаимодействия с функциями операционной системы, в частности — для управления файлами и каталогами. Чтобы выполнить навигацию по файловой системе, нужно применить одну из функций модуля — os.walk().

Фрагмент кода ниже находит все папки и файлы в указанной директории и выводит их полный путь на экран. Вот как он работает:

  • функция os.walk() проходит по всем файлам и папкам в указанной директории и предоставляет три значения: (1) текущая папка, (2) список подпапок и (3) список файлов;
  • затем используется os.path.join() для получения полного пути к файлу или папке.

После этого путь выводится на экран:

import os

def main():
    directory = "highload_today_directory"

    for root, dirs, files in os.walk(directory):
        print("Исходный каталог:", root)
        print("Вложенные папки:")
        for dir_name in dirs:
            print(os.path.join(root, dir_name))
        print("Файлы:")
        for file_name in files:
            print(os.path.join(root, file_name))
        print()

if __name__ == "__main__":
    main()

Аргументы функции os.walk()

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

Синтаксис функции предусматривает также три необязательных аргумента:

  • Так, если передать функции os.walk() аргумент topdown с логическим значением False, перебор выполняется от вложенных каталогов к внешним. Соответственно, если этот параметр принимает значение True (по умолчанию), обход идет от верхнего уровня к внутренним директориям.
  • Другой необязательный аргумент — onerror, функция-обработчик ошибок (по умолчанию None).
  • И последний необязательный аргумент — followlinks (по умолчанию False). Это логическое значение, указывающее, нужно ли следовать символическим ссылкам. При значении followlinks=False символические ссылки игнорируются, а обход ограничен только текущей структурой директорий.

Преимущества os.walk()

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

При этом функция os.walk() не возвращает все значения сразу, а вместо этого возвращает особый тип объекта — объект-генератор. Он генерирует значения по мере надобности, запоминая текущее состояние.

То есть, если у вас есть цикл for, вы можете остановить обход директорий, если в этом есть необходимость, а затем продолжить с этого момента.

Например, это может выглядеть так:

import os

start_path = '/какой-то/длинный/путь/к/директории'
generator = os.walk(start_path)

# Проходимся по первым 206 файлам
for root, dirs, files in generator:
    for file in files:
        # Обработка файла
        print(os.path.join(root, file))
        # Выключаем обход после 206 файлов
        if len(files) > 206:
            break
    else:
        continue
    break

# Снова запускаем обход с этапа, на котором остановились
for root, dirs, files in generator:
    for file in files:
        # Обработка файла
        print(os.path.join(root, file))

Когда мы используем объект-генератор в цикле for, он автоматически получает новые значения из os.walk() на каждой итерации. Это означает, что информация о директориях и файлах генерируется по мере обхода файловой системы, а не загружается сразу.

В случаях, когда идет обработка большого массива данных, скажем, миллиона файлов, такой подход экономит приличный объем памяти, требуемый для хранения этих значений.

Обратите внимание на синтаксис в адресе пути — для разных ОС он будет свой. Путь, указанный на Linux и macOS будет содержать прямой слеш (/), в то время как путь на Windows будет выглядеть так:

start_path = 'C:\\Users\\Username\\Documents' 

Либо с префиксом на указание сырой (raw) строки для которой обратный слеш не экранируется:

start_path = r'C:\Users\Username\Documents'

Примеры использования функции os.walk()

Нахождение дубликатов

Стандартная библиотека Python содержит модуль hashlib, который можно задействовать в паре с функцией os.walk() для поиска в директориях файлов-дубликатов. В этом случае программа будет сравнивать их хеш-суммы и делать вывод об идентичности данных:

import os
import hashlib

def get_file_hash(file_path):
    """Определяет хеш файла"""
    with open(file_path, 'rb') as f:
        data = f.read()
        file_hash = hashlib.sha256(data).hexdigest()
    return file_hash

def find_duplicate_files(start_path):
    """Выявляет идентичные файлы в указанном каталоге, а также во всех вложенных каталогах"""
    file_hashes = {}  # Словарь для записи хешей файлов
    duplicate_files = []  # Список для хранения дубликатов файлов

    for root, dirs, files in os.walk(start_path):
        for file_name in files:
            file_path = os.path.join(root, file_name)
            file_hash = get_file_hash(file_path)
            if file_hash in file_hashes:
                duplicate_files.append((file_path, file_hashes[file_hash]))
            else:
                file_hashes[file_hash] = file_path

    return duplicate_files

start_path = '/path/to/directory'
duplicates = find_duplicate_files(start_path)
if duplicates:
    print("Обнаружены дубликаты:")
    for file1, file2 in duplicates:
        print(file1, "и", file2)
else:
    print("Файлов с идентичным содержанием не обнаружено")

В коде выше идет обращение к функции get_file_hash(), чтобы вычислить хеш каждого файла по алгоритму SHA-256. После этого хеш и путь к файлу сохраняются в словарь file_hashes. Если будет найден файл с аналогичным хешем, он добавится в список duplicate_files.

Пакетное переименование

Предположим, необходимо переименовать группу файлов в директории C:\foto, добавив к каждому префикс Highloadtoday_. В этом случае мы можем использовать код:

import os

start_dir = start_path = 'C:\\foto'
add_prefix = 'Highloadtoday_'

for root, dirs, files in os.walk(start_dir):
    for file in files:
        file_path = os.path.join(root, file)
        edit_file_name = add_prefix + file
        edit_file_path = os.path.join(root, edit_file_name)
        os.rename(file_path, edit_file_path)
        print(file_path, edit_file_name)

Обратите внимание! Переменная edit_file_name в коде остается неизменной на протяжении выполнения скрипта.

Даже если в файловом менеджере вручную вернуть имя файла к исходному состоянию, переменная edit_file_name остается с префиксом Highloadtoday_.

Поэтому в консоли Python будет ошибочно писать в названии файла Highloadtoday_Highloadtoday_Highloadtoday_....., добавляя префикс в начало имени при каждом следующем запуске скрипта (даже если мы переименовали файл).

Чтобы устранить этот мелкий баг, просто используйте другую функцию модуля — os.path.basename(). Она позволит считать имя файла без пути и добавить префикс корректно:

import os

start_dir = 'C:\\foto'
add_prefix = 'Highloadtoday_'
for root, dirs, files in os.walk(start_dir):
    for file in files:
        if not file.startswith(add_prefix):
            file_path = os.path.join(root, file)
            file_name = os.path.basename(file_path)  # Получаем имя файла без пути
            edit_file_name = add_prefix + file_name  # Добавляем префикс к имени файла
            edit_file_path = os.path.join(root, edit_file_name)
            os.rename(file_path, edit_file_path)
            print(file_path, edit_file_name)

Заключение

Теперь вы знаете, как в Python легко и просто обходить директории, получая информацию о каталогах и файлах вашей файловой системы. Функция os.walk() эффективна при работе с большим объемом данных, а также легко комбинируется с прочими стандартными командами Python для выполнения сложных операций над файловой системой.

Подробнее про работу с модулем OS вы можете узнать из этого видео:

Останні статті

Обучение Power BI – какие онлайн курсы аналитики выбрать

Сегодня мы поговорим о том, как выбрать лучшие курсы Power BI в Украине, особенно для…

13.01.2024

Work.ua назвал самые конкурентные вакансии в IТ за 2023 год

В 2023 году во всех крупнейших регионах конкуренция за вакансию выросла на 5–12%. Не исключением…

08.12.2023

Украинская IT-рекрутерка создала бесплатный трекер поиска работы

Unicorn Hunter/Talent Manager Лина Калиш создала бесплатный трекер поиска работы в Notion, систематизирующий все этапы…

07.12.2023

Mate academy отправит работников в 10-дневный оплачиваемый отпуск

Edtech-стартап Mate academy принял решение отправить своих работников в десятидневный отпуск – с 25 декабря…

07.12.2023

Переписки, фото, история браузера: киевский программист зарабатывал на шпионаже

Служба безопасности Украины задержала в Киеве 46-летнего программиста, который за деньги устанавливал шпионские программы и…

07.12.2023

Как вырасти до сеньйора? Девелопер создал популярную подборку на Github

IT-специалист Джордан Катлер создал и выложил на Github подборку разнообразных ресурсов, которые помогут достичь уровня…

07.12.2023