Aller au contenu principal
TaskForge 3.0 : votre IA lit vos tâches.

Convertir les tâches Obsidian entre formats

Obsidian Tasks n’a aucune commande qui réécrit un coffre d’un format à un autre. Sa documentation le dit. Les conversions ci-dessous sont des scripts et des recettes qui font le travail, chacun testé sur les lignes d’exemple de la documentation du plugin, plus la seule conversion pour laquelle un outil existe : d’une ligne de tâche à un fichier de tâche, et inversement.

Rédigé pour Obsidian Tasks 8.6, Task Genius 9.13 et TaskNotes 4.14, octobre 2026. Les noms de champ et les symboles figurent dans l’aide-mémoire.

Avant de changer quoi que ce soit

  1. Sauvegarder le coffre. Copiez le dossier ou validez-le dans git. Un script qui réécrit 4 000 lignes doit pouvoir s’annuler facilement.
  2. Travailler d’abord sur une copie. Lancez la conversion sur une copie du coffre, ouvrez-la dans Obsidian et exécutez l’une de vos requêtes de tâches habituelles. Comparez les totaux avec l’original.
  3. Convertir, puis changer le plugin. Obsidian Tasks lit un seul format à la fois. Convertissez d’abord les lignes, puis changez le format de tâche dans ses réglages, pour que le plugin ne voie jamais un coffre à moitié converti.
  4. Vérifier ce qui reste. Cherchez dans le coffre les anciens symboles (📅, ⏳, ⏫ pour les emoji ; due::, repeat:: pour Dataview) afin de retrouver les lignes que la recette a ignorées.

Quelle conversion vous faut-il

De Vers Comment
Lignes en emoji Champs Dataview Le script ou la recette de rechercher-remplacer ci-dessous.
Champs Dataview Lignes en emoji Le script ou la recette inverse ci-dessous.
L’un ou l’autre Task Genius Rien à réécrire. Task Genius lit les deux sur la même ligne. Choisissez dans ses réglages lequel il écrit.
Lignes de tâche Fichiers de tâche TaskNotes convertit une ligne à la fois. La ligne de commande de TaskForge en convertit beaucoup d’un coup.
Fichiers de tâche Lignes de tâche La ligne de commande de TaskForge, avec un aperçu de tout ce qui serait perdu.

Des emoji aux champs Dataview

Chaque emoji et sa valeur deviennent un champ entre crochets. Les emoji de priorité deviennent un champ priority avec un mot, et le texte de récurrence passe à l’intérieur de ses crochets. Exécutez les remplacements dans cet ordre : dates et priorité d’abord, récurrence en dernier, pour que le texte de récurrence s’arrête là où commence le crochet suivant.

Avant et après

Avant
- [ ] 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
Après
- [ ] 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]

Rechercher et remplacer, un champ à la fois

Ces motifs fonctionnent dans tout éditeur qui permet une recherche par regex dans plusieurs fichiers, comme VS Code, qui écrit le texte capturé sous la forme $1. Activez le mode regex et la casse. Contrairement au script, ils s’appliquent à toutes les lignes, pas seulement aux cases à cocher.

Champ Rechercher Remplacer par
📅 (?:📅|📆|🗓️?)\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]

La même chose sous forme de script

Enregistrez ceci sous emoji_to_dataview.py et lancez python3 emoji_to_dataview.py Inbox.md Projects/*.md. Il ne touche que les lignes de case à cocher, écrit deux espaces avant chaque champ comme le fait Obsidian Tasks, et convertit aussi les symboles alternatifs d’échéance et de date planifiée : 📆, 🗓 et ⌛.

#!/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)

Des champs Dataview aux emoji

L’inverse lit [key:: value] comme (key:: value) et écrit les emoji standard. Les champs qu’il ne connaît pas, comme [project:: Website], restent intacts sur la ligne, et une priorité écrite sous forme de nombre est laissée telle quelle car les plugins ne s’accordent pas sur le sens des nombres.

Avant
- [ ] 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]
Après
- [ ] 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

Appliqué à la sortie du script précédent, il restitue exactement les lignes d’exemple ci-dessus. Les vrais coffres sont moins ordonnés : les lignes qui utilisaient 📆, 🗓 ou ⌛ reviennent en 📅 ou ⏳, et une ligne dont la description est vide gagne une espace.

Enregistrez ceci sous dataview_to_emoji.py et lancez-le de la même façon.

#!/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)

Ce que la conversion ne gère pas

  • Une ligne avec du texte entre deux champs. Obsidian Tasks lit depuis la fin de la ligne : il n’avait donc pas lu ces champs au départ.
  • Un lien de bloc comme ^abc123 en fin de ligne. Les scripts le laissent où il est, c’est-à-dire là où Obsidian l’attend.
  • La syntaxe propre à Task Genius : heures après les dates, priorités [#A], champs projet et contexte, règles de récurrence iCalendar. Laissez ces lignes telles quelles ou convertissez-les à la main.
  • Les règles de récurrence qu’un format écrit différemment. Vérifiez quelques tâches récurrentes après le changement, surtout celles avec when done.
  • Les tâches récurrentes qui ont déjà des copies terminées dans le fichier. Ces copies sont de simples tâches terminées et se convertissent comme n’importe quelle autre ligne.
  • Les lignes dans des blocs de code. Les scripts travaillent ligne par ligne et ignorent les délimiteurs : convertissez donc à la main les notes qui citent des exemples.
  • Un champ non reconnu laissé en fin de ligne, comme [custom:: x]. Obsidian Tasks lit depuis la fin : il s’arrête là et ignore les champs convertis qui précèdent.
  • Une règle 🔁 suivie d’un #tag. La récurrence n’est pas convertie : placez le tag avant elle ou convertissez cette ligne à la main.
  • Les tâches dans des citations ou des callouts (lignes qui commencent par > - [ ]). Les scripts les ignorent.
  • Une heure après une date, comme 14:30. Elle reste en dehors du champ converti. Obsidian Tasks n’a pas de champ d’heure : seul Task Genius la lit.

Des lignes de tâche aux fichiers de tâche

Un fichier de tâche est une note dont les champs de la tâche sont dans le frontmatter YAML, le format qu’utilise TaskNotes. Tous les champs d’une ligne n’y ont pas leur place. Voici comment les champs correspondent aux propriétés de TaskNotes.

Où va chaque champ

Sur une ligne de tâche Dans un fichier de tâche Remarque
📅 2026-11-03
due: 2026-11-03
Même nom.
⏳ 2026-11-01
scheduled: 2026-11-01
Même nom.
🛫 2026-11-10
start: 2026-11-10
TaskNotes n’a pas de date de début. Gardez-la comme propriété personnalisée si vous en avez besoin.
➕ 2026-10-01
dateCreated: 2026-10-01T08:00:00Z
Écrite sous forme d’horodatage ISO.
✅ 2026-10-20
completedDate: 2026-10-20
Le statut devient une valeur « terminé », et la date va dans completedDate.
⏫
priority: high
Utilise les valeurs de votre liste de priorités TaskNotes. La liste par défaut a trois niveaux, pas cinq : décidez donc comment les cinq se correspondent.
🔁 every month
recurrence: "DTSTART:20261103;FREQ=MONTHLY"
Devient une règle iCalendar. every month avec une date d’échéance au 2026-11-03 devient DTSTART:20261103;FREQ=MONTHLY.
#finance
tags:
  - finance
Deviennent une liste YAML, sans le dièse.
🏁 delete
onCompletion: delete
Pas de propriété TaskNotes. Conservé comme simple clé de frontmatter que TaskNotes ignore.
🆔 parts1
id: parts1
Pas de propriété TaskNotes. Les dépendances dans TaskNotes pointent vers des chemins de fichier, pas vers des ID.
⛔ parts1
blockedBy:
  - uid: "Tasks/Order parts.md"
    reltype: FINISHTOSTART
Devient une entrée blockedBy qui nomme le fichier de l’autre tâche.

Une ligne à la fois avec TaskNotes

TaskNotes a une commande Convert to TaskNote et un bouton de conversion à côté des cases à cocher, que vous pouvez activer dans ses réglages de fonctionnalités. L’un comme l’autre crée un nouveau fichier de tâche à partir de la ligne et remplace la ligne par un lien vers lui. Bien pour quelques tâches, lent pour un coffre entier.

Beaucoup d’un coup avec la ligne de commande de TaskForge

TaskForge est une application distincte, et son outil en ligne de commande (aussi le moteur de son serveur MCP) convertit des tâches entre ligne et fichier, dans les deux sens, une par une ou en lot. Il exige un coffre configuré pour les fichiers de tâche, car il doit savoir les reconnaître. Commencez par l’aperçu. Une validation en lot doit répéter le nombre de tâches trouvées par l’aperçu : une requête trop large ne peut donc pas convertir plus que prévu.

Aperçu, puis conversion, de chaque tâche portant le tag #home
taskforge convert --query 'tag:home' --to tasknotes --folder Tasks --dry-run
taskforge convert --query 'tag:home' --to tasknotes --folder Tasks --acknowledge-count 2

Un vrai passage

Dans Inbox.md
- [ ] Send invoice to Acme ⏫ 🔁 every month 📅 2026-11-03 #finance
Tasks/Send invoice to Acme.md
---
title: Send invoice to Acme
status: open
priority: high
tags:
  - finance
  - task
recurrence: "DTSTART:20261103;FREQ=MONTHLY"
due: 2026-11-03
---

La priorité ⏫ est devenue high et every month est devenu une règle iCalendar ancrée sur la date d’échéance. Lors d’un second passage, une date de début, une action à l’achèvement et un ID de tâche ont été conservés comme simples clés de frontmatter (start, onCompletion, id) au lieu d’être supprimés. La commande refuse toute tâche qu’elle ne peut pas convertir entièrement. Convertir un fichier dans les notes ajoute à la ligne le tag d’identification du fichier, task.

Pour aller dans l’autre sens, nommez une note de destination et commencez par l’aperçu :

taskforge convert --query 'tag:home' --to inline --folder Inbox.md --dry-run

Questions fréquentes

Comment convertir mes emoji Obsidian Tasks au format Dataview ?

Obsidian Tasks n’a pas de commande de conversion. Ne changez le format de tâche dans ses réglages qu’après avoir réécrit les lignes, avec un rechercher-remplacer par regex ou un script comme celui de cette page. Sauvegardez d’abord et testez sur une copie.

Changer le format de tâche dans Obsidian Tasks convertit-il mes tâches existantes ?

Non. Le réglage change la manière dont le plugin lit et écrit à partir de là. Les lignes dans l’ancien format ne sont plus lues comme des champs tant que vous ne les réécrivez pas.

Comment transformer beaucoup de tâches à case à cocher en fichiers TaskNotes ?

TaskNotes convertit une ligne à la fois. Pour un lot, la ligne de commande de TaskForge convertit chaque tâche qui correspond à une requête, après un essai à blanc. Dans les deux cas, vérifiez que les champs sans propriété TaskNotes, comme les dates de début, sont bien là où vous le souhaitez.

Dois-je convertir si j’utilise Task Genius ?

En général non. Task Genius lit les champs en emoji et à crochets sur la même ligne : les coffres mixtes fonctionnent donc tels quels. Convertir n’aide que si vous utilisez aussi Obsidian Tasks ou Dataview, qui lisent chacun un seul style.

Les scripts peuvent-ils abîmer mes notes ?

Ils ne modifient que les lignes de case à cocher et uniquement les champs qu’ils reconnaissent, mais ils réécrivent les fichiers sur place. Sauvegardez d’abord, lancez-les sur une copie et comparez avant de leur confier le vrai coffre.