21 — Работа с файлами и папками | Питон и КИЛИ

Содержание

  • Содержание папки
  • Работа с путями к файлам и папкам
  • Манипуляции с файлами и папками

Содержание папки

Модуль стандартной библиотеки os (от «operation system») предоставляет множество полезных функций для произведения системных вызовов. Одна из базовых функций этого модуля — os.listdir.

>>> import os

>>> file_list = os.listdir()  # список файлов и папок в директории, где запущена программа
>>> file_list = os.listdir('.')  # синоним
>>> file_list = os.listdir('C:/Users')  # список имен файлов и папок в данной папке

С точки зрения операционной системы нет разницы между файлом, папкой или другим подобным объектом, типа ссылки. Поэтому os.listdir() возвращает список как файлов, так и папок. Обратите внимание, что порядок элементов возвращаемого списка не регламентируется, если вам нужно их отсортировать не забудьте сделать это:

>>> import os

>>> unsorted_file_list = os.listdir()
>>> sortetd_file_list = sorted(unsorted_file_list)

Работа с путями к файлам и папкам

Модуль os содержит подмодуль os.path, который позволяет работать с путями файлов и папок. Импортировать этот модуль отдельно не нужно, достаточно выполнить import os.

Присоединение одной части пути к другой

Работа с путями к файлам и папкам как с простыми строками чревата множеством ошибок и может создать проблемы при переносе программы между различными операционными системами. Правильный путь объединить две части пути — это использование os.path.join:

>>> import os

>>> dirpath = '../books'
>>> # Здесь filename - имя файла, а не путь от места запуска программы до него:
>>> for filename in os.listdir(dirpath):
...     # filepath = dirname + filename - сработает неправильно, так как будет не хватать "/"
...     filepath = os.path.join(dirname, filename)  # поставит "/" или "\" за нас
...     with open(filepath, encoding='utf-8') as fd:
...         if 'нагваль' in fd.read():
...             print('Книга ' + filename + ' об индейцах')

Извлечение имени файла из пути

Функция os.path.split совершает обратное действие — отрезает имя файла или ниже лежащей папки от пути:

>>> import os

>>> path = './work/project/version8/final.txt'
>>> dirpath, filename = os.path.split(path)
>>> print(dirpath)
./work/project/version8
>>> print(filename)
final.txt
>>> project_dir, version_dir = os.path.split(dirpath)
>>> print(project_dir)
./work/project
>>> print(version_dir)
version8

Извлечение расширения

Кроме того, может пригодиться функция os.path.splitext, котоая отрезает расширение файла:

>>> import os
>>> path = './work/project/version12/final.txt'
>>> base, ext = os.path.splitext(path)
>>> print(base, ext, sep='\n')
./work/project/version12/final
.txt

Проверка типа файла

Кроме прочего, модуль os.path содержит функции для проверки существования файла и для определения его типа:

>>> import os

>>> path = './kursach/text'
>>> if os.path.exists(path):
...     print(path, 'существует')
...     if os.path.isfile(path):
...         print(path, '— это файл')
...     elif os.path.isdir(path):
...         print(path, '— это папка')
...     else:
...         print(path, '— это ни файл и ни папка')
... else:
...     print(path, 'не существует')

Манипуляции с файлами и папками

Производите все манипуляции с файлами с осторожностью, придерживайтесь правила «семь раз отмерь — один раз отрежь». Не забывайте программно производить все возможные проверки перед выполнением операций.

Создание файла

Нет ничего проще, чем создать пустой файл, достаточно открыть несуществующий файл с флагом 'x':

>>> with open('empty.txt', 'x'):
...     pass

Конечно, можно было бы использовать флаг 'w', но тогда уже существующий файл был бы стёрт. С флагом 'x' open либо создаст новый файл, либо выбросит ошибку.

Создание папки

Для создания новой папки используйте os.mkdir(name). Эта функция выбросит ошибку, если по указанному пути уже существует файл или папка. Если вам нужно создать сразу несколько вложенных папок, то смотрите функцию os.makedirs(name, exist_ok=False).

Перемещение и переименование

Для удобной манипуляции с файлами и папками в стандартной библиотеки Python существует специальный модуль shutil. Функция shutil.move(source, destination) позволяет вам переместить любой файл или папку (даже непустую). Обратите внимание, что если destination — это уже существующая папка, то файл/папка будет перемещена внутрь неё, в остальных случаях файл/папка будут скопированы точно по нужному адресу. В случае успеха, функция вернёт новое местоположение файла. Если destination существует и не является папкой, то будет выброшена ошибка.

>>> import shutil

>>> source = 'my_poem.txt'
>>> destination = 'trash'
>>> # Создаем папку назначения
>>> os.mkdir(destination)
>>> # Перенесем файл внутрь папки
>>> path = shutil.move(source, destination)
>>> print(path)
trash/my_poem.txt
>>> # Перенесем файл обратно
>>> new_name = 'poem.txt'
>>> final_path = shutil.move(path, new_name)
>>> print(final_path)
poem.txt

Как же переименовать файл? Несмотря на то, что os содержит специальную функцию для переименования, нужно понимать, что в рамках одной файловой системы перемещение и переименование — это одно и то же. Когда вы переименовываете файл, его содержимое не переписывается на носителе в другое место, просто файловая система теперь обозначает его положение другим путём.

Копирование

Скопировать файл можно с помощью функции shutil.copy(source, destination). Правила расположения копии будут те же, что и при использовании shutil.move, за тем исключением, что если destination существует и не является файлом, то он будет заменён и ошибки это не вызовет.

Скопировать папку для операционной системы сложнее, ведь мы всегда хотим скопировать не только папку, но и её содержимое. Для копирования папок используйте shutil.copytree(source, destination). Обратите внимание, что для этой функции destination всегда должно быть путём конечного расположения файлов и не может быть уже существующей папкой.

Удаление

Удалить файл можно с помощью функции os.remove, а пустую папку с помощью функции os.rmdir.

А вот для удаления папки с содержимым вновь понадобится shutil. Для удаления такой папки используйте shutil.rmtree.

Будьте осторожны, команды удаления стирают файл, а не перемещают его в корзину, вне зависимости от операционной системы! После такого удаления восстановить файл может быть сложно или вовсе невозможно.

Домашняя работа

  1. В текущей папке лежат файлы с расширениями .mp3, .flac и .oga. Создайте папки mp3, flac, oga и положите туда все файлы с соответствующими расширениями.
  2. В текущей папке лежит две других папки: vasya и mila, причём в этих папках могут лежать файлы с одинаковыми именами, например vasya/kursovaya.doc и mila/kursovaya.doc. Скопируйте все файлы из этих папок в текущую папку назвав их следующим образом: vasya_kursovaya.doc, mila_test.pdf и т.п.
  3. В текущей папке лежат файлы следующего вида: S01E01.mkv, S01E02.mkv, S02E01.mkv и т.п., то есть все файлы начинаются с S01 или S02. Создайте папки S01 и S02 и переложите туда соответствующие файлы.
  4. В текущей папке лежат файлы вида 2019-03-08.jpg, 2019-04-01.jpg и т.п. Отсортируйте файлы по имени и переименуйте их в 1.jpg, 2.jpg, …, 10.jpg, и т.д.
  5. В текущей папке лежат две другие папки: video и sub. Создайте новую папку watch_me и переложите туда содержимое указанных папок (сами папки класть не надо).
  6. В текущей папке лежат файлы типа Nina_Stoletova.jpg, Misha_Perelman.jpg и т.п. Переименуйте их переставив имя и фамилию местами.
  7. В текущей папке лежит файл list.tsv, в котором с новой строки написаны имена некоторых других файлов этой папки. Создайте папку list и переложите в неё данные файлы.

Для тестирования вашей программы положите в репозиторий файлы и папки с соответствующими именами. Файлы должны быть пустыми, если не указано обратного.