Obsidianのタスクを書式間で変換する
Obsidian Tasksには、保管庫をある書式から別の書式へ書き換えるコマンドがありません。同プラグインの文書にもそう書かれています。以下の変換は、それを行うスクリプトとレシピです。どれも同プラグイン自身の文書にあるサンプル行で検証してあります。加えて、ツールが存在する唯一の変換として、タスク行からタスクファイルへ、またその逆も扱います。
Obsidian Tasks 8.6、Task Genius 9.13、TaskNotes 4.14を対象に、2026年10月に作成しました。フィールド名と記号はチートシートに載っています。
変更の前に
- 保管庫をバックアップする. フォルダをコピーするか、gitにコミットします。4,000行を書き換えるスクリプトは、簡単に元へ戻せるようにしておくべきです。
- まずコピーで作業する. 保管庫のコピーで変換を実行し、Obsidianで開いて、普段使うタスクのクエリを1つ実行します。件数を元の保管庫と比べてください。
- 変換してから、プラグインを切り替える. Obsidian Tasksが読む書式は同時に1つです。先に行を変換してから、設定でタスク書式を変更すれば、プラグインが変換途中の保管庫を見ることはありません。
- 残りを確認する. 古い記号(絵文字なら 📅、⏳、⏫、Dataviewなら due::、repeat::)を保管庫内で検索し、レシピが飛ばした行を探します。
必要な変換はどれか
| 変換元 | 変換先 | 方法 |
|---|---|---|
| 絵文字の行 | Dataviewフィールド | 下のスクリプトまたは置換レシピ。 |
| Dataviewフィールド | 絵文字の行 | 下の逆変換のスクリプトまたはレシピ。 |
| どちらでも | Task Genius | 書き換えは不要です。Task Geniusは同じ行の両方を読みます。どちらを書くかは設定で選びます。 |
| タスク行 | タスクファイル | TaskNotesは1行ずつ変換します。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のようにファイル横断の正規表現検索ができるエディタで動作します。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と同じく各フィールドの前にスペースを2つ書き、別表記の期限と予定の記号 📆、🗓、⌛ も変換します。
#!/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 前のスクリプトの出力に対して実行すると、上のサンプル行がそのまま戻ります。実際の保管庫はここまできれいではありません。📆、🗓、⌛ を使っていた行は 📅 または ⏳ に戻り、説明が空の行にはスペースが1つ加わります。
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)
変換が扱わないもの
- 2つのフィールドの間にテキストがある行。Obsidian Tasksは行末から読むので、そもそもそれらのフィールドを読んでいません。
- 行末の ^abc123 のようなブロックリンク。スクリプトはそのまま残しますが、そこがObsidianの期待する位置です。
- Task Genius専用の構文:日付の後ろの時刻、[#A] 形式の優先度、プロジェクトとコンテキストのフィールド、iCalendarの繰り返しルール。これらの行はそのままにするか、手で変換してください。
- 書式によって表記が異なる繰り返しルール。切り替えた後で、特に when done を含むものを中心に、いくつか確認してください。
- 完了済みのコピーがすでにファイル内にある繰り返しタスク。コピーは通常の完了タスクであり、他の行と同じように変換されます。
- コードブロック内の行。スクリプトは行単位で動作し、フェンスを認識しないため、例を引用しているノートは手で変換してください。
- [custom:: x] のような認識されないフィールドが行末に残っている場合。Obsidian Tasksは行末から読むので、そこで読み取りが止まり、手前の変換済みフィールドは無視されます。
- 🔁 のルールの後ろに #タグ がある場合。繰り返しは変換されないまま残るので、タグをルールの前に移すか、その行を手で変換してください。
- 引用ブロックやコールアウト内のタスク(> - [ ] で始まる行)。スクリプトはこれらをスキップします。
- 日付の後ろの 14:30 のような時刻。変換後のフィールドの外に残ります。Obsidian Tasksには時刻フィールドがないため、読めるのはTask Geniusだけです。
タスク行からタスクファイルへ
タスクファイルは、タスクのフィールドをYAMLフロントマターに持つノートで、TaskNotesが使う書式です。行のフィールドのすべてが対応先を持つわけではありません。フィールドがTaskNotesのプロパティにどう対応するかを示します。
各フィールドの行き先
| タスク行 | タスクファイル | 備考 |
|---|---|---|
📅 2026-11-03 | | 同じ名前です。 |
⏳ 2026-11-01 | | 同じ名前です。 |
🛫 2026-11-10 | | TaskNotesに開始日はありません。必要ならカスタムプロパティとして残してください。 |
➕ 2026-10-01 | | ISOタイムスタンプで書かれます。 |
✅ 2026-10-20 | | ステータスが完了の値になり、日付は completedDate に入ります。 |
⏫ | | TaskNotesの優先度一覧にある値を使います。既定の一覧は5段階ではなく3段階なので、5段階をどう対応させるかを決めてください。 |
🔁 every month | | iCalendarのルールになります。期限日が 2026-11-03 の every month は、DTSTART:20261103;FREQ=MONTHLY になります。 |
#finance | | ハッシュ記号なしのYAMLリストになります。 |
🏁 delete | | TaskNotesのプロパティにはありません。TaskNotesが無視する通常のフロントマターのキーとして残ります。 |
🆔 parts1 | | TaskNotesのプロパティにはありません。TaskNotesの依存関係は、IDではなくファイルパスを指します。 |
⛔ parts1 | | 相手のタスクのファイルを指す blockedBy のエントリになります。 |
TaskNotesで1行ずつ
TaskNotesには Convert to TaskNote コマンドがあり、機能設定でチェックボックスの横に変換ボタンを表示することもできます。どちらも、行から新しいタスクファイルを作り、その行をそのファイルへのリンクに置き換えます。数件なら十分ですが、保管庫全体には遅すぎます。
TaskForgeのコマンドラインでまとめて
TaskForgeは独立したアプリで、そのコマンドラインツール(MCPサーバーの基盤でもあります)は、行とファイルの間のタスク変換を、どちらの方向でも、1件ずつでも一括でも実行します。タスクファイルを認識する方法を知る必要があるため、タスクファイル用に設定された保管庫が必要です。まずプレビューしてください。一括実行の確定には、プレビューで見つかったタスクの件数を再度指定する必要があるので、広すぎるクエリで意図した以上に変換されることはありません。
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が破棄されず、通常のフロントマターのキー(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は1行ずつ変換します。まとめて行うなら、TaskForgeのコマンドラインが、クエリに一致するすべてのタスクをドライランの後で変換します。どちらの場合も、開始日のようにTaskNotesのプロパティがないフィールドが、意図した場所に収まっているか確認してください。
Task Geniusを使うなら、変換は必要ですか?
たいていは不要です。Task Geniusは絵文字と角括弧のフィールドを同じ行で読むため、混在した保管庫もそのまま動きます。変換が役立つのは、片方のスタイルしか読まないObsidian TasksやDataviewも併用する場合だけです。
スクリプトでノートが壊れることはありますか?
変更するのはチェックボックスの行だけで、認識したフィールドだけですが、ファイルは上書きされます。実際の保管庫に使う前に、バックアップを取り、コピーで実行し、差分を比べてください。