Konwersja zadań Obsidian między formatami
Obsidian Tasks nie ma polecenia, które przepisuje sejf z jednego formatu na drugi. Mówi o tym jego dokumentacja. Poniższe skrypty i przepisy robią to zadanie, każdy sprawdzony na przykładowych liniach z dokumentacji samej wtyczki, plus jedna konwersja, do której istnieje narzędzie: linia zadania na plik zadania i z powrotem.
Napisane dla Obsidian Tasks 8.6, Task Genius 9.13 i TaskNotes 4.14, październik 2026. Nazwy pól i symbole są wymienione w ściądze.
Zanim cokolwiek zmienisz
- Zrób kopię zapasową sejfu. Skopiuj folder lub zacommituj go w git. Skrypt przepisujący 4 000 linii powinno być łatwo cofnąć.
- Najpierw pracuj na kopii. Uruchom konwersję na kopii sejfu, otwórz ją w Obsidian i wykonaj jedno ze swoich zwykłych zapytań o zadania. Porównaj liczby z oryginałem.
- Najpierw skonwertuj, potem przełącz wtyczkę. Obsidian Tasks czyta jeden format naraz. Najpierw skonwertuj linie, potem zmień format zadań w jego ustawieniach, żeby wtyczka nigdy nie zobaczyła w pół skonwertowanego sejfu.
- Sprawdź, co zostało. Przeszukaj sejf pod kątem starych symboli (📅, ⏳, ⏫ dla emoji; due::, repeat:: dla Dataview), aby znaleźć linie pominięte przez przepis.
Jakiej konwersji potrzebujesz
| Z | Na | Jak |
|---|---|---|
| Linie z emoji | Pola Dataview | Skrypt lub przepis na znajdź i zamień poniżej. |
| Pola Dataview | Linie z emoji | Skrypt odwrotny lub przepis poniżej. |
| Dowolny | Task Genius | Nie ma czego przepisywać. Task Genius czyta oba w tej samej linii. Który z nich zapisuje, wybierasz w jego ustawieniach. |
| Linie zadań | Pliki zadań | TaskNotes konwertuje po jednej linii. Wiersz poleceń TaskForge konwertuje wiele naraz. |
| Pliki zadań | Linie zadań | Wiersz poleceń TaskForge, z podglądem wszystkiego, co by przepadło. |
Z emoji na pola Dataview
Każde emoji wraz z wartością staje się polem w nawiasach. Emoji priorytetu zamieniają się w pole priority ze słowem, a tekst powtarzania trafia do nawiasów. Wykonuj zamiany w tej kolejności: najpierw daty i priorytet, powtarzanie na końcu, żeby tekst powtarzania kończył się tam, gdzie zaczyna się następny nawias.
Przed i po
- [ ] 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] Znajdź i zamień, jedno pole naraz
Te wzorce działają w każdym edytorze z wyszukiwaniem regex w wielu plikach, takim jak VS Code, który zapisuje przechwycony tekst jako $1. Włącz tryb regex i rozróżnianie wielkości liter. W przeciwieństwie do skryptu działają na każdej linii, nie tylko na polach wyboru.
| Pole | Znajdź | Zamień na |
|---|---|---|
| 📅 | (?:📅|📆|🗓️?)\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] |
To samo jako skrypt
Zapisz go jako emoji_to_dataview.py i uruchom: python3 emoji_to_dataview.py Inbox.md Projects/*.md. Dotyka tylko linii z polami wyboru, wstawia dwie spacje przed każdym polem tak jak Obsidian Tasks, a także konwertuje zapasowe symbole terminu i daty zaplanowanej 📆, 🗓 i ⌛.
#!/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)
Z pól Dataview na emoji
Odwrotny skrypt czyta zarówno [key:: value], jak i (key:: value) i zapisuje standardowe emoji. Pola, których nie zna, jak [project:: Website], zostają w linii nietknięte, a priorytet zapisany liczbą jest pomijany, bo wtyczki nie zgadzają się co do znaczenia liczb.
- [ ] 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 Uruchomiony na wyniku poprzedniego skryptu zwraca dokładnie powyższe przykładowe linie. Prawdziwe sejfy są mniej uporządkowane: linie z 📆, 🗓 lub ⌛ wracają jako 📅 lub ⏳, a linia z pustym opisem zyskuje spację.
Zapisz go jako dataview_to_emoji.py i uruchom tak samo.
#!/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)
Czego konwersja nie obsługuje
- Linii z tekstem między dwoma polami. Obsidian Tasks czyta od końca linii, więc tych pól i tak by nie przeczytał.
- Linku blokowego, takiego jak ^abc123, na końcu linii. Skrypty zostawiają go na miejscu, czyli tam, gdzie oczekuje go Obsidian.
- Składni tylko dla Task Genius: godzin po datach, priorytetów [#A], pól projektu i kontekstu, reguł powtarzania iCalendar. Zostaw te linie w spokoju albo skonwertuj je ręcznie.
- Reguł powtarzania, które jeden format zapisuje inaczej. Po przełączeniu sprawdź kilka zadań cyklicznych, zwłaszcza z when done.
- Zadań cyklicznych, które mają już w pliku ukończone kopie. Kopie to zwykłe ukończone zadania i konwertują się jak każda inna linia.
- Linii wewnątrz bloków kodu. Skrypty działają linia po linii i nie znają bloków, więc notatki cytujące przykłady skonwertuj ręcznie.
- Nierozpoznane pole na końcu linii, np. [custom:: x]. Obsidian Tasks czyta od końca, więc zatrzymuje się na nim i pomija skonwertowane pola przed nim.
- Reguła 🔁 po której stoi #tag. Powtarzanie zostaje nieskonwertowane, więc przenieś tag przed nią albo skonwertuj tę linię ręcznie.
- Zadania w cytatach lub calloutach (linie zaczynające się od > - [ ]). Skrypty je pomijają.
- Godzina po dacie, np. 14:30. Zostaje poza skonwertowanym polem. Obsidian Tasks nie ma pola godziny, więc czyta ją tylko Task Genius.
Z linii zadań na pliki zadań
Plik zadania to notatka z polami zadania we frontmatterze YAML, w formacie używanym przez TaskNotes. Nie każde pole linii ma tam swoje miejsce. Tak pola mapują się na właściwości TaskNotes.
Gdzie trafia każde pole
| W linii zadania | W pliku zadania | Uwaga |
|---|---|---|
📅 2026-11-03 | | Ta sama nazwa. |
⏳ 2026-11-01 | | Ta sama nazwa. |
🛫 2026-11-10 | | TaskNotes nie ma daty startowej. Zachowaj ją jako właściwość niestandardową, jeśli jej potrzebujesz. |
➕ 2026-10-01 | | Zapisywana jako znacznik czasu ISO. |
✅ 2026-10-20 | | Status staje się wartością „ukończone”, a data trafia do completedDate. |
⏫ | | Używa wartości z Twojej listy priorytetów TaskNotes. Lista domyślna ma trzy poziomy, nie pięć, więc zdecyduj, jak mapuje się pięć. |
🔁 every month | | Staje się regułą iCalendar. every month przy terminie 2026-11-03 zamienia się w DTSTART:20261103;FREQ=MONTHLY. |
#finance | | Stają się listą YAML, bez krzyżyka. |
🏁 delete | | Brak właściwości TaskNotes. Zachowane jako zwykły klucz frontmatter, który TaskNotes ignoruje. |
🆔 parts1 | | Brak właściwości TaskNotes. Zależności w TaskNotes wskazują ścieżki plików, nie ID. |
⛔ parts1 | | Staje się wpisem blockedBy wskazującym plik drugiego zadania. |
Po jednej linii z TaskNotes
TaskNotes ma polecenie Convert to TaskNote oraz przycisk konwersji obok pól wyboru, który możesz włączyć w ustawieniach funkcji. Każde z nich tworzy z linii nowy plik zadania i zastępuje linię linkiem do niego. W sam raz na kilka zadań, wolne dla całego sejfu.
Wiele naraz z wierszem poleceń TaskForge
TaskForge to osobna aplikacja, a jej narzędzie wiersza poleceń (będące też silnikiem jej serwera MCP) konwertuje zadania między linią a plikiem, w obu kierunkach, pojedynczo lub zbiorczo. Potrzebuje sejfu skonfigurowanego pod pliki zadań, bo musi wiedzieć, jak je rozpoznawać. Najpierw podgląd. Zbiorcze zatwierdzenie musi powtórzyć liczbę zadań znalezionych w podglądzie, więc zbyt szerokie zapytanie nie skonwertuje więcej, niż zamierzano.
taskforge convert --query 'tag:home' --to tasknotes --folder Tasks --dry-run
taskforge convert --query 'tag:home' --to tasknotes --folder Tasks --acknowledge-count 2 Prawdziwe uruchomienie
- [ ] 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
--- Priorytet ⏫ stał się high, a every month stało się regułą iCalendar zakotwiczoną na terminie. W drugim uruchomieniu data startowa, akcja po ukończeniu i ID zadania zostały zachowane jako zwykłe klucze frontmatter (start, onCompletion, id), a nie odrzucone. Polecenie odmawia każdego zadania, którego nie umie skonwertować w całości. Konwersja pliku z powrotem na linię dodaje do linii tag identyfikujący plik, task.
Aby pójść w drugą stronę, wskaż notatkę docelową i najpierw zrób podgląd:
taskforge convert --query 'tag:home' --to inline --folder Inbox.md --dry-run Powiązane
Pytania, które ludzie zadają
Jak skonwertować emoji Obsidian Tasks na format Dataview?
Obsidian Tasks nie ma polecenia konwersji. Zmień format zadań w jego ustawieniach dopiero po przepisaniu linii, używając znajdź i zamień z regex albo skryptu takiego jak ten na tej stronie. Najpierw zrób kopię zapasową i przetestuj na kopii.
Czy zmiana formatu zadań w Obsidian Tasks skonwertuje moje istniejące zadania?
Nie. Ustawienie zmienia tylko to, jak wtyczka czyta i zapisuje od tej chwili. Linie w starym formacie przestają być czytane jako pola, dopóki ich nie przepiszesz.
Jak zamienić wiele zadań z polami wyboru w pliki TaskNotes?
TaskNotes konwertuje po jednej linii. Dla całej partii wiersz poleceń TaskForge konwertuje każde zadanie pasujące do zapytania, najpierw na sucho. Tak czy inaczej sprawdź, czy pola bez właściwości w TaskNotes, takie jak daty startowe, wylądowały tam, gdzie chcesz.
Czy w ogóle muszę konwertować, jeśli używam Task Genius?
Zwykle nie. Task Genius czyta pola z emoji i w nawiasach w tej samej linii, więc sejfy mieszane działają bez zmian. Konwersja pomaga tylko wtedy, gdy używasz też Obsidian Tasks lub Dataview, z których każdy czyta jeden styl.
Czy skrypty mogą uszkodzić moje notatki?
Zmieniają tylko linie z polami wyboru i tylko rozpoznawane pola, ale przepisują pliki w miejscu. Zrób najpierw kopię zapasową, uruchom na kopii i porównaj wyniki, zanim powierzysz im prawdziwy sejf.