Сегодня говорим о таком важном инструменте для работы с файловой системой, как функция 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 вы можете узнать из этого видео:
Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…
Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…
Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…
В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…
Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…
Дедлайн (от англ. deadline — «крайний срок») — это конечная дата стачи проекта или задачи…