====== Работа с файловой системой ======
===== Пути к файлам =====
В 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"
- Просто
- Всегда работает
- Неперенасимо
===== Работа с путями как с объектами =====
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:')
- Сложнее
- Иногда приходится приводить к строкам
- Переносимо
===== Некоторые функции =====
=== Основные модули для работы с путями ===
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 КБ (зависит от ФС).
* Можно получать уведомления об изменении файлов от ОС, но это платформозависимо (модули ''inotify''pip и ''watchdog''pip).