はじめに
Obsidian の Vault を zip にして Notion にインポートすると、フォルダ構造もノート本文もそのまま再現される。ここまでは驚くほど素直に進む。
ところが画像だけが再現されない。ノートの中に
![[画像名.png]]
という文字列がそのまま残り、画像は表示されない。添付フォルダは空の殻として作られる。
この復旧を Notion AI にやらせた。作業自体はうまくいったのだが、行き当たりばったりに進めたせいでかなり遠回りをした。同じことをやる人が最短距離を通れるよう、手順とプロンプトをまとめておく。
結論を先に書くと、効率を決めるのは Notion AI のプロンプトではなく、インポート前に Vault を測っておくことである。筆者の Vault はノート 2,659 ファイルあったが、画像の埋め込みは 115 箇所・30 ファイルにしかなく、しかもその半分以上が 4 ファイルに固まっていた。これを先に知っていれば、全ノートを見て回る必要はなかった。
移行の全体像
ポイントは、テキストと画像で通る経路が違うことである。
| テキスト | 画像 | |
|---|---|---|
| 経路 | 設定 → インポート → テキスト & Markdown | Notion AI にファイルを添付 |
| 主な制限 | zip 1つあたり 5GB | 200MB 程度で弾かれる |
| やってくれること | 構造・本文の再現 | ファイル名で照合して挿入 |
インポート機能は Obsidian の画像記法を解釈しないので、画像を復旧するには別経路で渡すしかない。そしてその別経路のほうが制限が厳しい。ここが全体の形を決めている。
なお、テキスト側の 5GB はまず問題にならない。Vault の容量の大半は画像であり、それはインポートでは取り込まれないからだ。筆者の Vault は全体 325MB だったが、Markdown だけなら 9.3MB しかない。「容量が大きいから分割しなければ」と身構える必要はない。
代わりに気にすべきは画像側である。ここは後述するとおり、全画像を渡す必要はない。
なぜ画像リンクだけ再現されないのか
![[画像名.png]] は Markdown の標準記法ではなく、Obsidian
独自の Wiki リンク記法である。Notion のインポータは標準的な Markdown
として解釈するため、この記法は画像として扱われず、ただの文字列として残る。
副作用として、画像ファイル自体もアップロードされない。zip の中に画像が入っていても、参照している記法が理解されない以上、Notion 側は「必要な添付ファイル」と認識しない。attachments フォルダは空のページとして作られる。
同じ理由で [[ノート名]]
形式の内部リンクも変換されない。こちらは移行後に手で張り直すことになる。
裏を返せば、残った ![[...]]
という文字列そのものが復旧作業のマーカーになる。Notion AI
に「この文字列が残っている箇所を探せ」と指示できるので、後の工程が安定する。消えてしまうよりずっと扱いやすい。
Step1 棚卸し — Vault を測る
移行前に、次の3つを出しておく。
- 画像の埋め込みが何箇所・何ファイルにあるか
- それがどのファイルに集中しているか
- 参照先の実体が存在しないものがどれだけあるか
Vault のルートで次を実行する。
1 | import os, re, collections |
筆者の Vault では次のようになった。
1 | 埋め込み 115 箇所 / 30 ファイル |
上位4ファイルで 71 箇所、全体の6割を超える。領収書のスクリーンショットを貼った経費精算メモである。作業の半分以上がここに集中していると分かっていれば、まずこの4ファイルを片付けてから残りに移るという順序が立つ。
3つめの「実体が無い 33 件」も重要で、これは次章で扱う。
「実体が無い」は zip の入れ忘れではない
Notion AI に復旧させると、最後に「見つからなかったファイル」の一覧が出る。このとき 「zip に入れ忘れたのだろう」と考えて再アップロードすると、時間を捨てることになる。
筆者の場合、未解決として報告された 33 件は、Vault のどこにも実体が存在しないファイルだった。移行前から Obsidian 上でリンクが切れていたのである。参照元はいずれも数か月前のデイリーノートやアーカイブで、画像を消したあとノート側の記述が残っていたのだろう。何度アップロードしても直らない。
Vault 全体で見ると、画像の埋め込み 552 箇所のうち 150 件のファイル名が実体なしだった。
移行は、こうした蓄積した壊れを可視化する機会でもある。先に数えておけば、AI の報告を見た瞬間に「これは元から切れていた分だ」と切り分けられる。逆に数えていないと、Notion 側の不具合を疑って調べ回ることになる。
Step2 何を持っていかないか決める
ここは他人のリストを真似ても意味がない。自分の Vault で容量順に並べて、上から判断するしかない。
1 | du -sm * .* 2>/dev/null | sort -rn | head -20 |
判断の観点は3つある。
(a) Obsidian 本体の設定 — .obsidian/
配下。Notion では一切使わない。誰でも該当する。
(b) プラグインが生成したキャッシュ・インデックス — ここが曲者で、普段の使い方によって大きさがまるで違う。筆者の場合、ノートをベクトル化して保持するプラグインのデータが 16MB・2,240 ファイルあった。プラグイン本体も、AI 連携系だけで 8MB を超えていた。ノート本文が 9.3MB しかないことを考えると、本体より周辺のほうが重い。
(c) ツールに読ませるために書いたノート — AI 用のカスタムプロンプト、エージェント向けの指示ファイルなど。これらは普通のフォルダに普通の Markdown として置いてあるので、パターンでは落とせない。1つずつ「Notion に要るか」を判断するしかない。
- と (b) はドットディレクトリを除外すれば機械的に片付く。厄介なのは (c) で、ツールを Vault に組み込んでいる人ほど、除外の判断が自分固有になり、他人の手順が使えなくなる。
そしてもう1つ、原則として:
要らないものは、入れてから消すのではなく、入れる前に落とす。
Notion に入れてから整理すると、ページの移動・削除・重複判定という作業が発生する。数千ページ規模になると、これは Notion AI に投げても相応の時間がかかる。zip を作る段階で除外しておけば、その工程が丸ごと消える。
画像は「参照されているものだけ」でよい
Notion AI はファイル名で照合するので、画像 zip はフォルダ構造を保つ必要がない。逆に言えば、本文から参照されていない画像を渡す意味もない。
Step1 のスクリプトを流用して、必要な画像だけを集める。
1 | import zipfile |
筆者の場合、Vault 全体の画像は 413 枚・294MB あったが、実際に必要だったのは 78 件・34.2MB だった。9分の1以下である。200MB の制限に対して余裕があり、圧縮も分割も不要になった。
ファイル名で照合する以上、同名ファイルが複数あると取り違える。上のコードは平坦に詰めるので、衝突があれば
need を作る段階で気づけるようにしておくとよい。
もし 200MB を超えるようなら、次の順で対処する。分割は最後の手段である。インポート単位ごとに扱いが分かれて面倒になる。
- 参照されていない画像を落とす(多くはこれで足りる)
- 長辺 2000px 程度に縮小して再圧縮する(筆者の環境で試したところ、サンプル 30 枚が 67.8MB → 9.4MB になった。Notion 上で見るだけなら十分な画質である)
- それでも収まらなければ分割する
Step3 テキストをインポートする
設定 → インポート → テキスト & Markdown から zip を読み込ませる。フォルダ構造を保ちたいので、個別ファイルではなくフォルダごと zip 化して渡す。
公式に明示されている制限は次のとおり。
- 1ファイルあたり 5MB(無料プラン)/ 50MB(有料プラン)
- zip 1つあたり 5GB
- テキスト & Markdown は 12時間あたり約 120 ファイル
- 10,000 ファイルを超えると失敗または部分的な取り込みになりやすい
zip の中身が数千ファイルでも、zip 自体は1つのインポートとして扱われる。
Step4 Notion AI で画像を復旧する
インポート直後に、以下を Notion AI に貼り付ける。データベース名やラベルの語彙は自分の環境に合わせて差し替える。
1 | ObsidianからエクスポートしたzipをNotionにインポートしました。以下の手順で構造化してください。 |
次に画像 zip を添付し、以下を貼る。
1 | アップロードしたzip内の画像ファイルを使って、![[...]] が残っているページを修復してください。 |
このプロンプトが安定して動く理由は3つある。
探索範囲を文字列で固定している。
「画像が抜けているページを探して」ではなく「![[...]]
が残っている箇所」と指定する。判断ではなく検索になるので、取りこぼしも誤爆も減る。
照合の規則を明示している。 「ファイル名で照合してください」と書くことで、パスやフォルダ構造に依存しなくなる。だから画像 zip を平坦に詰めてよい。
報告を最後に要求している。 「見つからなかったファイルの一覧」があるので、どこまで終わったかが分かる。
実務上の注意も3つ。
冪等に再実行できる。
大量のページ移動やプロパティ設定は時間がかかり、途中で中断されることがある。すでに処理済みのページには
![[...]]
が残っていないので、「続きを実行して」で再開すれば二重処理にならない。この性質があるので、一度に大量に投げても壊れない。
ラベルの語彙は先に決めておく。 AI に任せると表記が揺れる。使う語を列挙して渡したほうが一貫する。
削除はゴミ箱行きなので戻せる。 重複判定を AI に任せるのは、この前提があってのことである。
筆者の場合、この2つのプロンプトで 28 ページに 75 個の画像・PDF が挿入された。
Step5 検証 — どこまでやれば終わりか
復旧後に残った ![[...]] を、次の3つに切り分ける。
| 残った理由 | 見分け方 | 対処 |
|---|---|---|
| 画像 zip に入れ忘れた | Vault に実体がある | 該当分だけ追加アップロードして追補 |
| Vault にも実体が無い | Step1 の missing に載っている |
直らない。Obsidian 側で元から切れていた |
| 画像化できない形式 | .base や .zip などの参照 |
PDF はファイル添付として挿入できる。それ以外は諦める |
Step1 を実行していれば、2つめは事前に判明している。AI の報告と突き合わせるだけで切り分けが終わる。
筆者の場合、未解決 36 件の内訳は「Vault に実体が無い 33
件」と「.base / .zip 形式 3
件」で、追加アップロードで直るものは1件も無かった。事前に数えていなければ、ここで
zip を作り直して再挑戦していたはずである。
なお、Obsidian の .base(Bases)ファイルへの参照は
Notion 側に持っていく手段がない。Vault 全体では 21
箇所あった。移行の対象外と割り切ることになる。
まとめ
- Notion のインポートは構造と本文を再現するが、Obsidian 独自の
![[...]]は生テキストとして残る。画像ファイル自体も上がらない - テキストは 5GB まで通る。容量が問題になるのは Notion AI に画像を渡す経路のほうで、こちらは 200MB 程度で弾かれる
- インポート前に、埋め込み箇所・集中しているファイル・実体の無い参照の3つを数える。作業量の見積もりと、後の切り分けが両方ここで決まる
- 画像は本文から参照されているものだけを平坦な zip に詰めればよい。筆者の場合 294MB が 34.2MB になった
- Notion AI へのプロンプトは「
![[...]]を探す」「ファイル名で照合する」「見つからなかったものを報告する」の3点を明示すると安定する - 復旧後に残った参照は「入れ忘れ」「元から切れていた」「形式的に無理」に切り分ける。Step1 を通していれば突き合わせるだけで済む
採らなかった方法
インポート前に ![[image.png]] を

へ一括置換する。 標準の Markdown
記法にしてしまえばインポータが解決してくれる可能性があり、うまくいけば
Notion AI
の工程が丸ごと不要になる。ただし相対パスの解決規則が期待どおりかは未検証で、今回は試していない。Vault
の一部で小さく試してから全体に適用するのが安全だろう。
zip を分割して複数回インポートする。 容量の問題はテキスト側では起きないので、必要になる場面は限られる。分割するとインポート単位ごとに別のトップレベルページができ、階層の組み直しが発生する。また zip をまたいでノートと添付が分かれると照合が壊れるので、切る位置にも気を配ることになる。