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

Функція 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 для виконання складних операцій із файловою системою.

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

Українські програмісти створили Lağoda QT — гру-головоломку кримськотатарською мовою

Українські програмісти створили безплатну гру-головоломку Lağoda QT.  Кожен рівень — вірш одного з видатних кримськотатарських…

07.05.2024

В Copilot для Microsoft 365 додали українську мову

Корпорація Microsoft оголосила про підтримку української мови у Copilot для Microsoft 365. Українська мова входить…

07.05.2024

Google безплатно навчатиме створювати чат-боти за допомогою Gemini. Потрібно тільки знання Python

Корпорація Google запустила реєстрацію задля участі в безплатній програмі Startup School: Gen AI. Програма безплатна…

07.05.2024

Вакансій і наймів більше, а зарплати — менше: що відбувалося на ринку праці у квітні

В квітні на ринку праці збільшилася кількість вакансій для IT-фахівців. На DOU та Djinni спостерігались…

07.05.2024

І всього лише $300. Китайці представили ноутбук на базі RISC-V для ШІ-девелоперів

Китайський стартап SpacemiT представив MuseBook — ноутбук на базі восьмиядерного процесора K1 RISC-V, орієнтований на…

06.05.2024

Учасники Brave1 створили ШІ-платформу HARVESTER для органів держбезпеки

Учасники Brave1, українська команда MATHESIS, розробила для органів держбезпеки платформу HARVESTER на основі штучного інтелекту.…

06.05.2024