Введение: Зачем программисту уметь работать с файлами?
Давайте честно, у кого из нас папка «Загрузки» не превращалась в свалку из документов, архивов и картинок с непонятными именами? Или, может, вы скачали сотню фоток с именами вроде DSC00123.JPG
и хотели бы дать им нормальные названия? Делать всё это руками — тоска и пустая трата времени.
И тут на сцену выходит Python со своим встроенным модулем os
.
Если коротко, это ваш швейцарский нож для работы с файловой системой прямо из кода. С его помощью можно узнать, где вы находитесь, посмотреть, какие файлы лежат в папке, создать новую директорию, переименовать тысячу файлов одним махом или удалить ненужный хлам. Это уже не просто абстрактные задачки, а реальная автоматизация своей рутины.
Эта статья — для новичков. Для тех, кто уже знает, что такое переменные и циклы, но пока боится подступиться к чему-то прикладному. Мы разберем самые нужные и частые команды модуля os
на простых примерах, без воды и заумных терминов.
Теория — это круто, но без практики она быстро выветривается. Поэтому в конце вас ждет не просто перечень команд, а ссылка на мой GitHub с практическими заданиями. Там мы и закрепим всё, о чем здесь поговорим. Поехали!
2. Подготовка к работе: import os
Давайте сразу к делу. Чтобы получить доступ ко всем этим командам, модуль os
нужно подключить к нашему скрипту. Это делается одной простой строкой в самом начале вашего .py
файла.
import os
И всё. Ничего дополнительно устанавливать через pip
не нужно, потому что os
— это часть стандартной библиотеки Python, он всегда под рукой.
Небольшой, но важный момент для общего развития:
В современном Python для работы с путями всё чаще используют модуль pathlib
. Он предлагает более удобный, объектно-ориентированный подход, и многие считают его более «питоничным».
Так почему мы начинаем с os
? Во-первых, это основа основ, и вы будете постоянно встречать его в огромном количестве существующего кода и примеров в интернете. Во-вторых, для простых, прямолинейных задач его синтаксис часто бывает понятнее новичку. Мы изучим базу, а к pathlib
вы всегда успеете прийти, когда почувствуете себя увереннее.
3. Где я? Навигация по файловой системе
Окей, модуль мы подключили. Но с чего начать? Прежде чем что-то создавать или удалять, неплохо бы осмотреться. Ваш скрипт, когда запускается, по умолчанию «не видит» ничего, кроме папки, из которой его запустили. Давайте научим его оглядываться по сторонам.
os.getcwd() — узнать текущую рабочую директорию
Первый и самый главный вопрос — где мы вообще находимся? Команда getcwd
(get current working directory) — это аналог команды pwd
в терминале Linux. Она моментально показывает полный путь к папке, в которой сейчас работает ваш скрипт.
import os
current_directory = os.getcwd()
print(f"Сейчас мой скрипт работает отсюда: {current_directory}")
Если вы запустите этот код, то увидите что-то вроде:
C:\Users\ИмяПользователя\Desktop\my_project
на Windows/home/ИмяПользователя/projects/my_project
на Linux или macOS
Просто и полезно.
os.listdir() — посмотреть, что находится в папке
Хорошо, мы знаем, где мы. А что вокруг нас? Команда listdir
покажет всё, что лежит в директории: и файлы, и другие папки. В ответ она возвращает обычный питоновский список со строками.
import os
# Если вызвать без аргументов, покажет содержимое текущей папки
whats_inside = os.listdir()
print("Внутри этой папки лежат:")
print(whats_inside)
# Вывод будет примерно таким:
# Внутри этой папки лежат:
# ['main.py', '.venv', 'data', 'requirements.txt']
Можно заглянуть и в любую другую папку, просто передав ей путь в качестве аргумента: os.listdir('C:/Users/ИмяПользователя/Documents')
.
os.chdir() — сменить текущую директорию
Это аналог команды cd
в терминале. Она позволяет скрипту «перейти» в другую папку и уже оттуда продолжать работу. Это одна из самых часто используемых команд.
Представим, что у нас есть папка data
. Давайте зайдем в нее.
import os
print(f"Сначала я здесь: {os.getcwd()}")
# 'Переходим' в папку data (она должна быть внутри текущей директории)
os.chdir('data')
print(f"Теперь я здесь: {os.getcwd()}")
А как вернуться обратно, на уровень выше? Для этого используется стандартное обозначение ..
.
# Возвращаемся на один уровень вверх
os.chdir('..')
print(f"И снова я здесь: {os.getcwd()}")
Важный момент: если вы попытаетесь перейти в папку, которой не существует, Python выдаст ошибку FileNotFoundError
, и скрипт упадет. Всегда будьте уверены, что директория, в которую вы переходите, действительно существует. Позже мы научимся это проверять.
4. Создаем и удаляем: управление папками и файлами
Окей, навигацию освоили. Давайте к самому интересному — будем что-то менять. Создавать папки для будущего порядка, переименовывать файлы и избавляться от мусора.
Работа с папками
os.mkdir()
— создать одну папку
Тут всё просто. mkdir
(make directory) создает новую папку в текущей директории.
import os
# Создаст папку 'reports' прямо здесь
os.mkdir('reports')
Важный нюанс: если папка reports
уже существует, скрипт упадет с ошибкой FileExistsError
.
os.makedirs()
— создать сразу несколько папок
А что, если нужно создать целую структуру? Например, archive/2025/photos
. Если попытаться сделать это через mkdir
, он сломается, потому что папки archive
еще нет. Вот тут-то и нужен makedirs
— он достаточно умен, чтобы создать всё дерево директорий за вас.
import os
# Эта команда создаст и 'archive', и вложенную в нее '2025', и 'photos'
os.makedirs('archive/2025/photos')
Это супер-удобно, и в 90% случаев вы будете использовать именно makedirs
.
os.rmdir()
— удалить пустую папку
rmdir
(remove directory) делает обратное — удаляет папку. Ключевое слово здесь — пустую. Если внутри директории что-то есть, Python откажется ее удалять и выдаст ошибку. Это такая защита от случайного сноса важных данных.
import os
# Сначала создадим, потом удалим
os.mkdir('temp_folder')
os.rmdir('temp_folder')
Работа с файлами
os.rename()
— переименовать или переместить файл
А вот тут кроется небольшой трюк. Команда rename
делает сразу две вещи.
-
Простое переименование:
import os # Сначала создадим файл, чтобы было с чем работать with open('old_name.txt', 'w') as f: f.write('some text') # А теперь переименуем его os.rename('old_name.txt', 'new_name.txt')
-
Перемещение файла: Если вторым аргументом указать путь в другую папку, файл переедет туда.
import os os.makedirs('archive') # Создадим папку для примера # Перемещаем наш файл в папку 'archive' os.rename('new_name.txt', 'archive/new_name.txt')
Это очень мощный прием: одной командой и переименовали, и переместили.
os.remove()
— удалить файл
Это прямой и беспощадный способ удалить файл. Никаких вопросов, никаких «вы уверены?». Просто берет и удаляет.
import os
# Удаляем файл, который только что переместили
os.remove('archive/new_name.txt')
ВНИМАНИЕ! ОЧЕНЬ ВАЖНЫЙ БЛОК!
Команды os.remove()
и os.rmdir()
удаляют файлы и папки НАВСЕГДА. Они не перемещают их в Корзину. Отменить это действие нельзя. Один неверный шаг в цикле — и можно случайно снести половину рабочего стола.
Золотое правило: прежде чем запускать скрипт, который что-то удаляет, сначала замените os.remove(path)
на print(f"Собираюсь удалить: {path}")
. Запустите, посмотрите на список и только потом, будучи на 100% уверенным, возвращайте команду удаления. Не рискуйте.
5. Путь к файлу: магия os.path
Казалось бы, что сложного в путях к файлам? Просто строка, да и всё.
Проблема: разные слэши
На Windows пути к файлам разделяются обратным слэшем: C:\Users\User\Documents
.
А на Linux и macOS — прямым: /home/user/documents
.
Если вы в своем коде жестко пропишете my_folder + '/' + my_file
, ваш скрипт прекрасно сработает на Linux, но сломается на Windows. Это главная головная боль, которую решает подмодуль os.path
.
os.path.join() — правильный способ собирать пути
Забудьте про склеивание строк со слэшами. Навсегда. Вместо этого используйте os.path.join()
. Эта функция сама понимает, на какой операционной системе она запущена, и подставляет правильный разделитель.
import os
# Просто перечисляем части пути через запятую
folder = 'documents'
filename = 'report.docx'
# os.path.join() сделает всю грязную работу за нас
full_path = os.path.join('C:', 'Users', 'User', folder, filename)
print(full_path)
# На Windows выведет: C:\Users\User\documents\report.docx
# На Linux вывело бы: C:/Users/User/documents/report.docx (с правильными слэшами)
Используйте эту функцию всегда. Это признак хорошего, переносимого кода.
basename и dirname — разбираем пути на запчасти
Часто нужно сделать обратное: из полного пути получить только имя файла или только путь к папке, в которой он лежит.
os.path.basename(path)
— возвращает имя файла.os.path.dirname(path)
— возвращает путь к директории.
import os
full_path = '/home/user/documents/report.docx'
filename = os.path.basename(full_path)
print(f"Имя файла: {filename}") # Выведет: Имя файла: report.docx
directory = os.path.dirname(full_path)
print(f"Путь к папке: {directory}") # Выведет: Путь к папке: /home/user/documents
Невероятно полезно, когда нужно работать с файлами, не зная их точных имен заранее.
Проверки — работаем безопасно
Это, возможно, самый важный блок в этой главе. Помните, мы говорили, что скрипт упадет, если попытаться перейти в несуществующую папку? Или создать папку, которая уже есть? Чтобы этого избежать, нужно проверять, существует ли путь, прежде чем что-то с ним делать.
os.path.exists(path)
— самая частая проверка. ВозвращаетTrue
, если путь (файл или папка) существует, иFalse
, если нет.os.path.isfile(path)
— возвращаетTrue
, только если это существующий файл.os.path.isdir(path)
— возвращаетTrue
, только если это существующая папка.
Вот как это выглядит на практике:
import os
path_to_check = 'archive'
if os.path.exists(path_to_check):
print(f"Путь '{path_to_check}' существует.")
if os.path.isdir(path_to_check):
print("И это папка!")
elif os.path.isfile(path_to_check):
print("И это файл!")
else:
print(f"Пути '{path_to_check}' не существует. Давайте создадим папку.")
os.makedirs(path_to_check)
Этот простой шаблон с if
делает ваш код в сто раз надежнее. Сначала проверяем, потом делаем. Всегда.
6. Собираем все вместе: пишем скрипт для сортировки файлов
Хватит теории. Давайте напишем что-то, что можно запустить и сразу увидеть результат. Помните проблему с папкой «Загрузки», которую мы обсуждали в самом начале? Вот ее мы и решим.
Постановка задачи:
У нас есть папка, заваленная разными файлами: картинками (.jpg
, .png
), документами (.pdf
, .docx
) и архивами (.zip
). Наша цель — написать скрипт, который:
Сам создаст внутри этой папки директории:
Images
,Documents
,Archives
иOther
.Пройдется по всем файлам.
Рассортирует каждый файл в соответствующую папку в зависимости от его расширения.
План-алгоритм скрипта (наша логика):
Прежде чем писать код, давайте проговорим шаги. Наш скрипт должен:
Определить путь к папке, где будем наводить порядок.
Получить список всего, что в ней лежит.
Запустить цикл и по очереди рассматривать каждый элемент из этого списка.
Внутри цикла первым делом проверить: это файл или папка? Сортируем мы только файлы.
Если это файл, смотрим на его расширение (то, что после последней точки в имени).
В зависимости от расширения, решаем, в какую целевую папку (
Images
,Documents
и т.д.) его нужно положить.Перед перемещением проверяем, а существует ли вообще эта целевая папка? Если нет — создаем ее.
Перемещаем файл в нужную папку.
Звучит логично. Теперь переведем это на язык Python.
Код:
import os
import shutil # Этот модуль мы не проходили, но его метод move надежнее для перемещения
# 1. УКАЖИТЕ ПУТЬ К ВАШЕЙ ПАПКЕ ДЛЯ СОРТИРОВКИ!
# ВАЖНО: Используйте двойные слэши \\ для Windows или одинарные / для Linux и macOS
PATH_TO_SORT = "C:\\Users\\YourUser\\Downloads\\TestFolder" # <-- ИЗМЕНИТЕ ЭТОТ ПУТЬ
# 2. Получаем список всех файлов и папок в директории
all_items = os.listdir(PATH_TO_SORT)
# 3. Проходимся по каждому элементу
for item in all_items:
# Собираем полный путь к файлу, чтобы с ним можно было работать
item_full_path = os.path.join(PATH_TO_SORT, item)
# 4. Проверяем, что это файл, а не папка
if os.path.isfile(item_full_path):
try:
# 5. Получаем расширение файла в нижнем регистре
extension = item.split('.')[-1].lower()
# 6. Определяем, в какую папку положить файл
target_folder = ''
if extension in ['jpg', 'jpeg', 'png', 'gif', 'bmp']:
target_folder = 'Images'
elif extension in ['pdf', 'docx', 'doc', 'txt', 'xlsx']:
target_folder = 'Documents'
elif extension in ['zip', 'rar', '7z']:
target_folder = 'Archives'
else:
target_folder = 'Other'
# Собираем путь к целевой папке
target_folder_path = os.path.join(PATH_TO_SORT, target_folder)
# 7. Проверяем, существует ли папка. Если нет - создаем.
if not os.path.exists(target_folder_path):
os.makedirs(target_folder_path)
print(f"Создана папка: {target_folder}")
# 8. Перемещаем файл
# Используем shutil.move, он корректно работает между разными дисками
# и в целом более предсказуем, чем os.rename для перемещения
shutil.move(item_full_path, target_folder_path)
print(f"Файл '{item}' перемещен в папку '{target_folder}'")
except Exception as e:
# На случай, если у файла нет расширения или возникла другая ошибка
print(f"Не удалось обработать файл '{item}'. Ошибка: {e}")
print("\nСортировка завершена!")
Вот и всё! Этот скрипт — отличный пример того, как несколько простых команд модуля os
(и одна из shutil
для надежности) могут превратиться в полезную программу-автоматизатор. Можете скопировать его, изменить путь и попробовать на тестовой папке.
7. Заключение и что дальше?
Ну вот и всё! Если вы дочитали до этого момента и попробовали запустить код, то поздравляю: вы сделали огромный шаг от написания абстрактных «hello, world» к созданию реально полезных скриптов.
Давайте быстро пробежимся по тому, что мы теперь умеем:
Осматриваться в файловой системе с помощью
getcwd
иlistdir
.Перемещаться между папками через
chdir
.Создавать и удалять папки (
mkdir
,makedirs
,rmdir
).Переименовывать, перемещать и удалять файлы (
rename
,remove
).И, что самое главное, — писать кросс-платформенный и безопасный код, используя проверки из
os.path
.
Мы собрали все эти знания в одном скрипте, который наводит порядок в папках. Это и есть настоящая автоматизация: скучную ручную работу мы переложили на плечи Python.
Куда двигаться дальше?
Мир работы с файлами не ограничивается одним модулем os
. Если эта тема вас зацепила, вот пара советов для дальнейшего изучения:
Посмотрите в сторону
pathlib
. Как я уже упоминал, это более современная и объектно-ориентированная библиотека для работы с путями. Код с ней часто выглядит чище и интуитивнее. Считать, чтоos
устарел — неправильно, но знать проpathlib
и уметь им пользоваться — это признак хорошего тона в современном Python.Попробуйте автоматизировать что-то свое. Подумайте, какие рутинные задачи с файлами вы выполняете на своем компьютере? Может, нужно бэкапить какие-то документы по расписанию? Или искать файлы-дубликаты? Попробуйте набросать для этого свой собственный скрипт.
Спасибо, что уделили время этой статье. Надеюсь, она была для вас полезной. А теперь — к самому главному.
8. Домашнее задание на GitHub
Как и обещал в самом начале, просто прочитать статью — недостаточно. Настоящие нейронные связи в мозгу формируются только тогда, когда вы сами пишете код, сталкиваетесь с ошибками и исправляете их.
Поэтому я подготовил для вас репозиторий, где вы сможете отточить все, о чем мы сегодня говорили.
>> Ссылка на репозиторий с заданиями на GitHub <<
Что вас ждет внутри? Не просто список задач, а нечто лучшее. Рядом с каждым заданием лежат готовые тесты, которые автоматически проверят ваш код. Вам не придется гадать, «а правильно ли я всё сделал?». Просто пишете решение, запускаете проверку, и она вам тут же скажет, всё ли работает как надо.
Вся подробная инструкция — как скачать репозиторий, как запустить тесты и что именно от вас требуется в каждом задании — находится в файле README.md
в корне репозитория.
Если что-то будет непонятно или заметите ошибку, не стесняйтесь создавать 'Issue' на GitHub. А пообщаться, задать вопросы и обсудить решения можно в моем телеграм-блоге — заходите, буду рад помочь: Cсылка.
Уверен, у вас все получится. Вперед, к практике
Markscheider
А зачем это делать в каждой итерации цикла? Не бог весть какая нагрузка на процессор, конечно, но все же...
Я бы перед циклом один создал структуру папок. Тем более она все равно захардкожена (Картинки Документы Архивы Прочее).
А если раздражают пустые папки - в конце программы проверил бы их и удалил те, в которых ничего не нападало...