はじめに

本記事では、Google Drive上のGoogleドキュメントを自動で取得し、個人のorg-roamナレッジベースにノートとして取り込むための自動化スクリプト fetch_drive_data.sh について解説します。

外出先のモバイルで調査した内容をうまくナレッジにするには?

解きたかった課題は「外出先で調査・思索した内容を、いかに効率よく個人のナレッジベース(org-roam)に集約するか」という点です。

現在スマートフォンでの情報収集やアイデアメモが大きな比重を占めています。 例えばスマートフォンのGeminiアプリは、調査や文章生成に非常に強力なツールです。

しかし、その内容をorg-roamのナレッジにするのは煩雑な手順が必要です。

  • google docsにエクスポートして
  • orgフォーマットに直し
  • org-roamのnodeとして追加する

このような手順を行う必要があります。手動で5ステップほどでしょうか。 少し多いですね。

一方で、GeminiアプリはGeminiの応答をGoogleドキュメントとして手軽にエクスポートできます。 Googleドキュメントとして保存する操作は、どのデバイスからでも非常に簡単です。 そのため、手軽なナレッジ追加自体は簡単に思えます。

これをうまく結合させようと思ったのが開発の発端でした。

ここからアイディアを発展させて特定のGoogle DriveをGeminiなどで調査した外部情報の「一時受け入れボックス(インボックス)」として機能させることを思いつきました。

orgzly の利用は却下した

当初は orgzly のようなモバイルアプリも検討しました。 これはorgファイルを直接モバイルでも扱えるようにするものです。 しかし、このアイディアは却下しました。

スマートフォン上で直接orgファイルのフォーマットを整えながら編集するのは、操作が煩雑に感じられたためです。 しかもGeminiアプリからの転記作業も必要です。

また、 orgzly データの同期は syncthing を用いるものが一般的なようでしたが、このアプリケーションがセキュアかどうか判断しかねたのです。

そのため、 orgzly を利用するのはやめました。

rcloneを利用してナレッジの取り込む方針とした

上記のアイディアを検討した結果、 rclone で取り込むことにしました。 そうすると必要なのはorg-roamにnodeとして取り込みを自動化する処理です。

ここまでくればあとは開発するのみです。 諸々ゴニョゴニョする必要はありますが、力技です。

具体的には以下の処理です。

  1. rclone を使って、指定したGoogle Driveフォルダからドキュメントを一括でダウンロードする。
  2. ダウンロードしたファイルを pandoc でorg-mode形式に変換する。
  3. 変換したファイルにorg-roam用のプロパティ(IDなど)を付与し、ノートとして所定のディレクトリに配置する。

この流れをシェルスクリプトに落とし込みます。

モバイルでGoogle Driveに保存、PCで取り込みという体験の完成

このshell scriptによってこのようなフローが実現できます。

  • モバイルで行うこと
    • 調査したことをGoogle Driveに保存
  • PCで行うこと
    • shellの実行

これによりモバイルで生まれた着想や調査結果を、コマンド一つでシームレスにナレッジに統合する仕組みの完成です。

参考)スクリプトの全体像

以下が、今回開発した fetch_drive_data.sh の全容です。参考に貼っておきます。

#!/bin/bash

# fetch_drive_data.sh: 指定したGoogle Driveフォルダ内のすべてのGoogleドキュメントを
#                      一括ダウンロードし、org-roamノートに変換してDBを同期するスクリプト

# --- 設定 ---
# Google DriveのフォルダIDを指定
FOLDER_ID="${your_folder_id}"
# org-roamのノートが保存されているディレクトリパスを指定
ORG_ROAM_DIR="org_sources/sketches/nodes/"
# 作成されるorgノートに設定するHugoのセクション
HUGO_NODES_SECTION="sketches/nodes"

# --- 初期化 ---
set -e # エラーが発生したらスクリプトを終了
TEMP_DIR=$(mktemp -d)
TMP_RCLONE_CONF="/tmp/rclone.conf.$$"

# スクリプト終了時に一時ファイルを必ず削除する
trap 'rm -f "$TMP_RCLONE_CONF"; rm -rf "$TEMP_DIR"' EXIT

# --- rclone設定 ---
echo "1. rcloneの設定を読み込み中..."
pass show rclone/config > "$TMP_RCLONE_CONF"
export RCLONE_CONFIG="$TMP_RCLONE_CONF"
echo "設定読み込み完了。"

# --- 一括ダウンロード ---
echo "2. Google Driveからドキュメントを一括ダウンロード中 (Folder ID: ${FOLDER_ID})..."
# --include "*.gdoc" でGoogleドキュメントのみを対象にする
rclone copy "gdrive:" --drive-root-folder-id "${FOLDER_ID}" "${TEMP_DIR}" -P -v

# ダウンロードされたファイルがあるか確認
if [ -z "$(find "$TEMP_DIR" -name "*.docx")" ]; then
  echo "ダウンロードされたdocxファイルが見つかりません。処理を終了します。"
  exit 0
fi
echo "一括ダウンロード完了。"

# --- ローカルでのループ処理 ---
echo "3. ダウンロードした各ファイルの処理を開始..."
for DOCX_FILE in "$TEMP_DIR"/*.docx; do
  echo "--------------------------------------------------"
  echo "処理中: $(basename "$DOCX_FILE")"

  # 3a. pandocでorgに変換
  BASENAME=$(basename "$DOCX_FILE" .docx)
  echo "  - pandocでorgに変換中..."
  PANDOC_ORG_FILE="${TEMP_DIR}/${BASENAME}.org"
  pandoc -f docx -t org "$DOCX_FILE" -o "$PANDOC_ORG_FILE" --wrap=none

  # 3b. org-roam用ファイルを作成
  echo "  - org-roamノートを作成中..."
  ROAM_ID=$(uuidgen)
  ROAM_BASENAME=$(echo "${BASENAME}" | tr ' ' '_')
  ROAM_FILE_PATH="${ORG_ROAM_DIR}$(date +%Y%m%d%H%M%S)-${ROAM_BASENAME}.org"

  {
      echo ":PROPERTIES:"
      echo ":ID:       ${ROAM_ID}"
      echo ":END:"
      echo "#+title: ${BASENAME}"
      echo "#+HUGO_SECTION: ${HUGO_NODES_SECTION}"
      echo "#+AUTHOR: moai"
      echo "#+HUGO_AUTO_SET_LASTMOD: t"
      echo "#+hugo_paired_shortcodes: reasoning"
      echo ""
    cat "$PANDOC_ORG_FILE"
  } > "$ROAM_FILE_PATH"
  echo "  - ノート作成完了: ${ROAM_FILE_PATH}"

done
echo "--------------------------------------------------"
echo "全てのファイルの処理が完了しました。"

# --- DB同期とHugoエクスポート ---
echo "4. org-roamデータベースを更新し、Hugoコンテンツをエクスポート中..."
emacs --batch -l ~/.emacs.d/init.el --eval '(progn (org-roam-db-sync) (my-hugo-export-all-org-sources))'
echo "DB同期とHugoエクスポートが完了しました。"

# --- Google Driveのクリーンアップ ---
echo "5. 処理済みのドキュメントをGoogle Driveから削除中..."
rclone delete "gdrive:" --drive-root-folder-id "${FOLDER_ID}" --include "*.gdoc" -P -v
echo "Google Driveのクリーンアップが完了しました。"

echo "全ての処理が正常に完了しました。"

実際にはこのshellをmakeコマンドにして実行できるようにしています。