Работа с файловой системой

Пути к файлам

В Windows пути:

  • Начинаются с имени диска (C:, D:, …)
  • Регистронезависимы (Hello.txt и hello.txt один файл)
  • Компоненты пути разделяются символом \

В POSIX системах пути:

  • Начинаются с корневой директории /
  • Регистрозависимы (Hello.txt и hello.txt разные файлы)
  • Компоненты пути разделяются символом /

Пути бывают:

  • Абсолютные (C:\python\python.exe, /usr/bin/python)
  • Относительные (..\python.exe, ../python)
  • Со специальными сокращениями %WINDIR%\notepad.exe, ~/file.txt

Работа с путями как со строками

Пути к файлам с точки зрения системы это текстовые строки.

filepath = r"C:\Windows\notepad.exe"
filepath = "/usr/bin/nano"
  1. Просто
  2. Всегда работает
  3. Неперенасимо

Работа с путями как с объектами

from pathlib import Path
p = Path(r"C:\Windows\notepad.exe")
p.parts # ('C:', 'Windows', 'notepad.exe')
p.parents[0] # PosixPath('C:/Windows')
p.parents[1] # PosixPath('C:')
  1. Сложнее
  2. Иногда приходится приводить к строкам
  3. Переносимо

Некоторые функции

Основные модули для работы с путями

import os
import os.path
import shutil

Текущая папка скрипта

os.getcwd() # '/home/f0ma'
os.chdir("/home/f0ma")

Пути абсолютные и относительные

os.getcwd() # '/home/f0ma'
p1 = os.path.relpath("/home/f0ma/test.txt")
# p1 == 'test.txt'
p2 = os.path.relpath("/usr/bin/bash")
# p2 == '../../usr/bin/bash'
p3 = os.path.abspath('../../usr/bin/bash')
# p3 == '/usr/bin/bash'

Компоненты пути

# Имя файла без пути
p4 = os.path.basename("/home/f0ma/test.txt")
# p4 == 'test.txt'

# Путь без имени
p5 = os.path.dirname("/home/f0ma/test.txt")
# p5 == '/home/f0ma'

# Компоненты пути
p6 = os.path.normpath("/home/f0ma/test.txt").split(os.sep)
# p6 == ['', 'home', 'f0ma', 'test.txt']

# Имя диска (только для Windows)
p7, _ = os.path.splitdrive(r"C:\Windows\notepad.exe")
# p7 == "C:"

# Расширение файла (последнее)
_, p8 = os.path.splitext(r"C:\Windows\notepad.exe")
# p8 == ".exe"

Существование файлов и папок

# Существование файла
s1 = os.path.isfile("/home/f0ma/test.txt")
#s1 == True

# Существование папки
s2 = os.path.isdir("/home/f0ma")
#s2 == True

Атрибуты файлов и папок

# Время создания
t2 = os.path.getctime("/home/f0ma/test.txt")
# t2 == 1509012699.5303257

# Время изменения
t1 = os.path.getmtime("/home/f0ma/test.txt")
# t1 == 1509012699.4743266

# Размер
s = os.path.getsize("/home/f0ma/test.txt")
# s == 18

Перемещение/копирование/удаление

# Создание одной папки
os.mkdir("/home/f0ma/test")

# Создание всех папок в пути
os.makedirs("/home/f0ma/test/test")

# Удаление файла
os.remove("/home/f0ma/test/test.txt")

# Удаление папки (пустой)
os.rmdir("/home/f0ma/test")

# Удаление папки с файлами рекурсивно
shutil.rmtree("/home/f0ma/test")

# Перемещения файла или папки
shutil.move("/home/f0ma/test", "/tmp/test")

# Копирование файла
shutil.copy("/home/f0ma/test.txt", "/home/f0ma/test2.txt")

# Копирование папки рекурсивно
shutil.copytree("/home/f0ma/test", "/tmp/test")

Список файлов по маске

Обход по маске — метод glob модуля glob.

import glob
import os

os.chdir("/home/f0ma/src/hesk273/docs/")

s1 = glob.glob("*.html")
# s1 == ['/home/f0ma/src/hesk273/docs/changelog.html',
#         ...
#        '/home/f0ma/src/hesk273/docs/step-by-step-guide.html']

s2 = glob.glob("/home/f0ma/src/**/**/*.css")
# s2 == ['/home/f0ma/src/pdfedit-0.4.5/doc/pdfedit.css',
#         ...
#        '/home/f0ma/src/hesk273/docs/docs_style.css']
Символ маски Значение
* Любое число любых символов
? Один любой символ
** Обойти все папки рекурсивно

Обход файлов

Рекурсивный обход файлов метод walk модуля os.

import os

for dirname, subdirs, files in os.walk("bin"):
    # dirname — имя текущей папки
    print(dirname)
    # subdirs — подпапки текущей папки
    print(subdirs)
    # files — файлы в текущей папке
    print(files)

Что еще нужно знать о путях

  • Если путь не абсолютный, то он вычисляется от текущей папки программы.
  • Обход глубоко вложенных деревьев может занимать очень много времени.
  • Разные файловые системы (ФС) имеют различные особенности в частности атрибуты и альтернативные потоки.
  • В Windows и POSIX различная схема управления правами на доступ к файлам, а еще есть такие вещи, как SELinux и ACL.
  • Минимальный размер файла и папки ~ 4 КБ (зависит от ФС).
  • Можно получать уведомления об изменении файлов от ОС, но это платформозависимо (модули inotifypip и watchdogpip).