Сегодня говорим о таком важном инструменте для работы с файловой системой, как функция 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() достаточно использовать аргумент top — путь к директории, с которой нужно выполнять обход файловой системы.
Синтаксис функции предусматривает также три необязательных аргумента:
os.walk() аргумент topdown с логическим значением False, перебор выполняется от вложенных каталогов к внешним. Соответственно, если этот параметр принимает значение True (по умолчанию), обход идет от верхнего уровня к внутренним директориям.onerror, функция-обработчик ошибок (по умолчанию None).followlinks (по умолчанию False). Это логическое значение, указывающее, нужно ли следовать символическим ссылкам. При значении followlinks=False символические ссылки игнорируются, а обход ограничен только текущей структурой директорий.За счет особенностей своей работы функция 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'
Стандартная библиотека 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 вы можете узнать из этого видео:
На фоне роста спроса на ликвидность в бычьем рынке 2025 года, криптозаймы снова выходят на…
Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…
Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…
Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…
В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…
Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…