Преобразование задач Obsidian между форматами
В Obsidian Tasks нет команды, которая переписывает хранилище из одного формата в другой. Об этом сказано в его документации. Ниже собраны скрипты и рецепты, которые справляются с задачей, каждый проверен на примерах строк из документации самого плагина, плюс единственное преобразование, для которого есть инструмент: строка задачи в файл задачи и обратно.
Написано по Obsidian Tasks 8.6, Task Genius 9.13 и TaskNotes 4.14, октябрь 2026 года. Названия полей и символы перечислены в шпаргалке.
Прежде чем что-то менять
- Сделайте резервную копию хранилища. Скопируйте папку или закоммитьте её в git. Скрипт, переписывающий 4 000 строк, должно быть легко откатить.
- Сначала работайте с копией. Запустите преобразование на копии хранилища, откройте её в Obsidian и выполните один из привычных запросов по задачам. Сравните количество с оригиналом.
- Сначала преобразуйте, потом переключайте плагин. Obsidian Tasks читает один формат за раз. Сначала преобразуйте строки, затем смените формат задач в его настройках, чтобы плагин никогда не видел наполовину преобразованное хранилище.
- Проверьте, что осталось. Поищите в хранилище старые символы (📅, ⏳, ⏫ для эмодзи; due::, repeat:: для Dataview), чтобы найти строки, которые рецепт пропустил.
Какое преобразование вам нужно
| Из | В | Как |
|---|---|---|
| Строки с эмодзи | Поля Dataview | Скрипт или рецепт поиска и замены ниже. |
| Поля Dataview | Строки с эмодзи | Обратный скрипт или рецепт ниже. |
| Любой | Task Genius | Переписывать нечего. Task Genius читает оба в одной строке. Какой из них он пишет, выбирается в его настройках. |
| Строки задач | Файлы задач | TaskNotes преобразует по одной строке. Командная строка TaskForge преобразует много сразу. |
| Файлы задач | Строки задач | Командная строка TaskForge с предпросмотром всего, что было бы потеряно. |
Из эмодзи в поля Dataview
Каждое эмодзи вместе со значением становится полем в скобках. Эмодзи приоритета превращаются в поле priority со словом, а текст повторения переезжает внутрь скобок. Выполняйте замены в таком порядке: сначала даты и приоритет, повторение в последнюю очередь, чтобы текст повторения заканчивался там, где начинается следующая скобка.
До и после
- [ ] Send invoice to Acme ⏫ 🔁 every month ➕ 2026-10-01 ⏳ 2026-11-01 📅 2026-11-03 #finance
- [x] Book flights 📅 2026-10-25 ✅ 2026-10-20
- [ ] Order parts 🆔 parts1
- [ ] Assemble 🛫 2026-11-10 ⛔ parts1 📅 2026-11-15 - [ ] Send invoice to Acme [priority:: high] [repeat:: every month] [created:: 2026-10-01] [scheduled:: 2026-11-01] [due:: 2026-11-03] #finance
- [x] Book flights [due:: 2026-10-25] [completion:: 2026-10-20]
- [ ] Order parts [id:: parts1]
- [ ] Assemble [start:: 2026-11-10] [dependsOn:: parts1] [due:: 2026-11-15] Поиск и замена, по одному полю
Эти шаблоны работают в любом редакторе с поиском по регулярным выражениям по файлам, например в VS Code, который записывает захваченный текст как $1. Включите режим регулярных выражений и учёт регистра. В отличие от скрипта, они применяются к каждой строке, а не только к флажкам.
| Поле | Найти | Заменить на |
|---|---|---|
| 📅 | (?:📅|📆|🗓️?)\s*(\d{4}-\d{2}-\d{2}) | [due:: $1] |
| ⏳ | (?:⏳|⌛)\s*(\d{4}-\d{2}-\d{2}) | [scheduled:: $1] |
| 🛫 | 🛫\s*(\d{4}-\d{2}-\d{2}) | [start:: $1] |
| ➕ | ➕\s*(\d{4}-\d{2}-\d{2}) | [created:: $1] |
| ✅ | ✅\s*(\d{4}-\d{2}-\d{2}) | [completion:: $1] |
| ❌ | ❌\s*(\d{4}-\d{2}-\d{2}) | [cancelled:: $1] |
| 🔺 | 🔺️? | [priority:: highest] |
| ⏫ | ⏫️? | [priority:: high] |
| 🔼 | 🔼️? | [priority:: medium] |
| 🔽 | 🔽️? | [priority:: low] |
| ⏬ | ⏬️? | [priority:: lowest] |
| 🏁 | 🏁\s*(keep|delete) | [onCompletion:: $1] |
| 🆔 | 🆔\s*([A-Za-z0-9_-]+) | [id:: $1] |
| ⛔ | ⛔\s*([A-Za-z0-9_-]+(?:\s*,\s*[A-Za-z0-9_-]+)*) | [dependsOn:: $1] |
| 🔁 | 🔁\s*([A-Za-z0-9, !]*[A-Za-z0-9])(?=\s*(?:\[|\^|$)) | [repeat:: $1] |
То же самое в виде скрипта
Сохраните его как emoji_to_dataview.py и запустите: python3 emoji_to_dataview.py Inbox.md Projects/*.md. Он затрагивает только строки с флажками, ставит два пробела перед каждым полем, как это делает Obsidian Tasks, и преобразует также запасные символы срока и запланированной даты 📆, 🗓 и ⌛.
#!/usr/bin/env python3
"""Rewrite Obsidian Tasks emoji fields to Dataview [key:: value] fields.
Usage: emoji_to_dataview.py NOTE.md [NOTE.md ...] (rewrites in place; back up first)
Only checkbox lines are touched. Run it on a copy of your vault first.
"""
import os
import re
import sys
DATE = r"(\d{4}-\d{2}-\d{2})"
ID = r"[A-Za-z0-9_-]+"
RULES = [
(rf"(?:📅|📆|🗓️?)\s*{DATE}", r"[due:: \1]"),
(rf"(?:⏳|⌛)\s*{DATE}", r"[scheduled:: \1]"),
(rf"🛫\s*{DATE}", r"[start:: \1]"),
(rf"➕\s*{DATE}", r"[created:: \1]"),
(rf"✅\s*{DATE}", r"[completion:: \1]"),
(rf"❌\s*{DATE}", r"[cancelled:: \1]"),
(r"🔺️?", "[priority:: highest]"),
(r"⏫️?", "[priority:: high]"),
(r"🔼️?", "[priority:: medium]"),
(r"🔽️?", "[priority:: low]"),
(r"⏬️?", "[priority:: lowest]"),
(r"🏁\s*(keep|delete)", r"[onCompletion:: \1]"),
(rf"🆔\s*({ID})", r"[id:: \1]"),
(rf"⛔\s*({ID}(?:\s*,\s*{ID})*)", r"[dependsOn:: \1]"),
# Last, so the rule text ends at the next bracket or the end of the line.
(r"🔁\s*([A-Za-z0-9, !]*[A-Za-z0-9])(?=\s*(?:\[|\^|$))", r"[repeat:: \1]"),
]
TASK = re.compile(r"^(\s*(?:[-*+]|\d+\.)\s+\[.\]\s)(.*)$")
for path in sys.argv[1:]:
out = []
for raw in open(path, encoding="utf-8", newline="").read().split("\n"):
cr = "\r" if raw.endswith("\r") else ""
line = raw[: len(raw) - len(cr)]
m = TASK.match(line)
if m:
head, body = m.groups()
for pattern, repl in RULES:
body = re.sub(pattern, repl, body)
body = re.sub(r"\s*(\[(?:due|scheduled|start|created|completion|cancelled|priority|onCompletion|id|dependsOn|repeat):: )", r" \1", body)
line = head + body
out.append(line + cr)
tmp = path + ".tmp"
with open(tmp, "w", encoding="utf-8", newline="") as fh:
fh.write("\n".join(out))
os.replace(tmp, path)
Из полей Dataview в эмодзи
Обратный скрипт читает и [key:: value], и (key:: value) и записывает стандартные эмодзи. Неизвестные ему поля, например [project:: Website], остаются в строке нетронутыми, а приоритет, записанный числом, не трогается, потому что плагины расходятся в том, что означают числа.
- [ ] Send invoice to Acme [priority:: high] [repeat:: every month] [created:: 2026-10-01] [scheduled:: 2026-11-01] [due:: 2026-11-03] #finance
- [x] Book flights [due:: 2026-10-25] [completion:: 2026-10-20]
- [ ] Order parts [id:: parts1]
- [ ] Assemble [start:: 2026-11-10] [dependsOn:: parts1] [due:: 2026-11-15] - [ ] Send invoice to Acme ⏫ 🔁 every month ➕ 2026-10-01 ⏳ 2026-11-01 📅 2026-11-03 #finance
- [x] Book flights 📅 2026-10-25 ✅ 2026-10-20
- [ ] Order parts 🆔 parts1
- [ ] Assemble 🛫 2026-11-10 ⛔ parts1 📅 2026-11-15 Если запустить его на результате предыдущего скрипта, вернутся строки из примеров выше в точности. Реальные хранилища менее аккуратны: строки с 📆, 🗓 или ⌛ возвращаются как 📅 или ⏳, а у строки с пустым описанием появляется пробел.
Сохраните его как dataview_to_emoji.py и запустите так же.
#!/usr/bin/env python3
"""Rewrite Dataview [key:: value] task fields to Obsidian Tasks emoji fields.
Usage: dataview_to_emoji.py NOTE.md [NOTE.md ...] (rewrites in place; back up first)
Reads [key:: v] and (key:: v). Only checkbox lines are touched.
"""
import os
import re
import sys
DATE = r"(\d{4}-\d{2}-\d{2})"
ID = r"[A-Za-z0-9_-]+"
def field(key, value):
return rf"[\[(]\s*{key}::\s*{value}\s*[\])]"
RULES = [
(field("due", DATE), r"📅 \1"),
(field("scheduled", DATE), r"⏳ \1"),
(field("start", DATE), r"🛫 \1"),
(field("created", DATE), r"➕ \1"),
(field("completion", DATE), r"✅ \1"),
(field("cancelled", DATE), r"❌ \1"),
(field("priority", "highest"), "🔺"),
(field("priority", "high"), "⏫"),
(field("priority", "medium"), "🔼"),
(field("priority", "low"), "🔽"),
(field("priority", "lowest"), "⏬"),
(field("onCompletion", "(keep|delete)"), r"🏁 \1"),
(field("id", f"({ID})"), r"🆔 \1"),
(field("dependsOn", rf"({ID}(?:\s*,\s*{ID})*)"), r"⛔ \1"),
(field("repeat", r"([A-Za-z0-9, !]*[A-Za-z0-9])"), r"🔁 \1"),
]
TASK = re.compile(r"^(\s*(?:[-*+]|\d+\.)\s+\[.\]\s)(.*)$")
for path in sys.argv[1:]:
out = []
for raw in open(path, encoding="utf-8", newline="").read().split("\n"):
cr = "\r" if raw.endswith("\r") else ""
line = raw[: len(raw) - len(cr)]
m = TASK.match(line)
if m:
head, body = m.groups()
for pattern, repl in RULES:
body = re.sub(pattern, repl, body, flags=re.I if "priority" in pattern else 0)
line = head + re.sub(r"[ \t]{2,}", " ", body).rstrip()
out.append(line + cr)
tmp = path + ".tmp"
with open(tmp, "w", encoding="utf-8", newline="") as fh:
fh.write("\n".join(out))
os.replace(tmp, path)
Что преобразование не обрабатывает
- Строка с текстом между двумя полями. Obsidian Tasks читает с конца строки, так что эти поля он и раньше не прочитал бы.
- Блочная ссылка вроде ^abc123 в конце строки. Скрипты оставляют её на месте, там, где её ожидает Obsidian.
- Синтаксис только Task Genius: время после дат, приоритеты [#A], поля проекта и контекста, правила повторения iCalendar. Такие строки оставьте как есть или преобразуйте вручную.
- Правила повторения, которые один формат записывает иначе. После переключения проверьте несколько повторяющихся задач, особенно с when done.
- Повторяющиеся задачи, у которых в файле уже есть выполненные копии. Копии это обычные выполненные задачи, и они преобразуются как любая другая строка.
- Строки внутри блоков кода. Скрипты работают построчно и о блоках кода не знают, поэтому заметки с цитируемыми примерами преобразуйте вручную.
- Нераспознанное поле в конце строки, например [custom:: x]. Obsidian Tasks читает с конца, поэтому останавливается на нём и игнорирует преобразованные поля перед ним.
- Правило 🔁, за которым идёт #тег. Повторение остаётся непреобразованным, поэтому поставьте тег перед ним или преобразуйте эту строку вручную.
- Задачи внутри цитат или выносок (строки, начинающиеся с > - [ ]). Скрипты их пропускают.
- Время после даты, например 14:30. Оно остаётся за пределами преобразованного поля. В Obsidian Tasks нет поля времени, так что читает его только Task Genius.
Из строк задач в файлы задач
Файл задачи это заметка с полями задачи во frontmatter YAML, формат, который использует TaskNotes. Не у каждого поля строки там есть место. Вот как поля соотносятся со свойствами TaskNotes.
Куда попадает каждое поле
| В строке задачи | В файле задачи | Примечание |
|---|---|---|
📅 2026-11-03 | | То же имя. |
⏳ 2026-11-01 | | То же имя. |
🛫 2026-11-10 | | В TaskNotes нет даты начала. Сохраните её как пользовательское свойство, если она нужна. |
➕ 2026-10-01 | | Записывается как метка времени ISO. |
✅ 2026-10-20 | | Статус становится значением «выполнено», а дата записывается в completedDate. |
⏫ | | Использует значения из вашего списка приоритетов TaskNotes. В списке по умолчанию три уровня, а не пять, так что решите, как сопоставить пять. |
🔁 every month | | Становится правилом iCalendar. every month при сроке 2026-11-03 превращается в DTSTART:20261103;FREQ=MONTHLY. |
#finance | | Становятся списком YAML, без решётки. |
🏁 delete | | Свойства TaskNotes для этого нет. Сохраняется как обычный ключ frontmatter, который TaskNotes игнорирует. |
🆔 parts1 | | Свойства TaskNotes для этого нет. Зависимости в TaskNotes указывают на пути файлов, а не на ID. |
⛔ parts1 | | Становится записью blockedBy, называющей файл другой задачи. |
По одной строке с помощью TaskNotes
В TaskNotes есть команда Convert to TaskNote и кнопка преобразования рядом с флажками, которую можно включить в настройках функций. Любой из способов создаёт новый файл задачи из строки и заменяет строку ссылкой на него. Подходит для нескольких задач, но для целого хранилища медленно.
Много сразу с помощью командной строки TaskForge
TaskForge это отдельное приложение, и его инструмент командной строки (он же движок его сервера MCP) преобразует задачи между строкой и файлом в любом направлении, по одной или массово. Ему нужно хранилище, настроенное на файлы задач, потому что он должен знать, как их распознавать. Сначала сделайте предпросмотр. Массовое выполнение должно повторить число задач, найденных при предпросмотре, поэтому слишком широкий запрос не преобразует больше, чем вы хотели.
taskforge convert --query 'tag:home' --to tasknotes --folder Tasks --dry-run
taskforge convert --query 'tag:home' --to tasknotes --folder Tasks --acknowledge-count 2 Реальный запуск
- [ ] Send invoice to Acme ⏫ 🔁 every month 📅 2026-11-03 #finance ---
title: Send invoice to Acme
status: open
priority: high
tags:
- finance
- task
recurrence: "DTSTART:20261103;FREQ=MONTHLY"
due: 2026-11-03
--- Приоритет ⏫ стал high, а every month стал правилом iCalendar с опорой на срок. Во втором запуске дата начала, действие при завершении и ID задачи сохранились как обычные ключи frontmatter (start, onCompletion, id), а не были отброшены. Команда отказывается от любой задачи, которую не может преобразовать целиком. При обратном преобразовании файла в строку к строке добавляется опознавательный тег файла, task.
Чтобы пойти в обратную сторону, укажите заметку назначения и сначала сделайте предпросмотр:
taskforge convert --query 'tag:home' --to inline --folder Inbox.md --dry-run Связанные материалы
Вопросы, которые задают чаще всего
Как преобразовать эмодзи Obsidian Tasks в формат Dataview?
В Obsidian Tasks нет команды преобразования. Меняйте формат задач в его настройках только после того, как перепишете строки с помощью замены по регулярным выражениям или скрипта вроде приведённого на этой странице. Сначала сделайте резервную копию и проверьте на копии.
Преобразует ли смена формата задач в Obsidian Tasks мои существующие задачи?
Нет. Настройка меняет только то, как плагин читает и пишет дальше. Строки в старом формате перестают читаться как поля, пока вы их не перепишете.
Как превратить много задач с флажками в файлы TaskNotes?
TaskNotes преобразует по одной строке. Для пакета командная строка TaskForge преобразует все задачи, подходящие под запрос, с предварительным пробным запуском. В любом случае проверьте, что поля без свойства в TaskNotes, например даты начала, оказались там, где вам нужно.
Нужно ли вообще преобразовывать, если я пользуюсь Task Genius?
Обычно нет. Task Genius читает поля с эмодзи и в скобках в одной строке, поэтому смешанные хранилища работают как есть. Преобразование имеет смысл, только если вы пользуетесь ещё и Obsidian Tasks или Dataview, каждый из которых читает один стиль.
Могут ли скрипты испортить мои заметки?
Они меняют только строки с флажками и только распознаваемые поля, но переписывают файлы на месте. Сначала сделайте резервную копию, запустите на копии и сравните результат, прежде чем доверять им настоящее хранилище.