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

Функция 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 вы можете узнать из этого видео:

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

Что такое прокси-сервер: пояснение простыми словами, зачем нужны прокси

Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…

21.11.2024

Что такое PWA приложение? Зачем необходимо прогрессивное веб-приложение

Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…

19.11.2024

Как создать игру на телефоне: программирование с помощью конструктора

Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…

17.11.2024

Google Bard: эффективный аналог ChatGPT

В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…

14.11.2024

Скрипт и программирование: что это такое простыми словами

Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…

12.11.2024

Дедлайн в разработке: что это такое простыми словами

Дедлайн (от англ. deadline — «крайний срок») — это конечная дата стачи проекта или задачи…

11.11.2024