Функція 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 для виконання складних операцій із файловою системою.
Сообщить об опечатке
Текст, который будет отправлен нашим редакторам: