Hugo から Quartz4に乗り換えて、Obsidian でBlog更新を完結させるで、一つ問題になったのがObsidianのノート内で張り付けていた画像が表示されないこと。 自分は /resources 配下にすべての添付ファイルが配置されているが、Quartzは特定のディレクトリを対象にビルドされる。つまり指定した特定のディレクトリ内部に画像が存在しない場合、参照時に画像が存在しないので、表示がされない。 quartzでページ生成時にもエラーがでている。

一番簡単なのは、すべてのresources を Quartzのビルド対象化に入れることだが、秘匿したいファイルも含まれているのでそれは避けたい。

可能なら Quartzでビルドされるファイルから参照されている添付ファイル(主に画像)のみ抽出して、指定されたディレクトリ配下に移動させれば解決できる。

image_move.sh

#!/bin/bash
 
SOURCE_DIR="/mnt/c/Users/hurut/Dropbox/obsidian/resources" # 移動元の画像ディレクトリ(移動対象の画像があるディレクトリ)
DEST_DIR="/mnt/c/Users/hurut/Dropbox/obsidian/public_blog/resources" # 移動先の画像ディレクトリ
OBSIDIAN_DIR="/mnt/c/Users/hurut/Dropbox/obsidian"     # Obsidian Vault のルートディレクトリ
MARKDOWN_DIR="/mnt/c/Users/hurut/Dropbox/obsidian/public_blog"  # 特定のディレクトリ配下のmarkdownファイルを対象とする
 
echo "SOURCE_DIR = $SOURCE_DIR"
echo "DEST_DIR = $DEST_DIR"
echo "OBSIDIAN_DIR = $OBSIDIAN_DIR"
echo "MARKDOWN_DIR = $MARKDOWN_DIR"
 
DRY_RUN=false  # Dry run モードの切り替え (true: 実行しない、false: 実行する)
 
# 1. Markdown ファイルを検索
find "$MARKDOWN_DIR" -type f -name "*.md" -print0 | while IFS= read -r -d $'\0' MARKDOWN_FILE; do
    
    # 2. Markdown ファイルから画像参照を抽出
    grep -oP '(?<=!\[\[).*?\.(png|jpg|jpeg|gif)(?=\]\])' "$MARKDOWN_FILE" | while IFS= read -r IMAGE_REF; do
        echo "MARKDOWN_FILE = $MARKDOWN_FILE"
        echo "IMAGE_REF = $IMAGE_REF"
 
        # 3. 画像参照からファイル名を抽出 (拡張子含む)
        IMAGE_FILENAME=$(echo "$IMAGE_REF" | sed 's/!\[\[//; s/\]\]//')
        echo "IMAGE_FILENAME = $IMAGE_FILENAME"
 
        # 4. 移動対象の画像の絶対パスを生成
        SOURCE_IMAGE_PATH="$SOURCE_DIR/$IMAGE_FILENAME"
        echo "SOURCE_IMAGE_PATH = $SOURCE_IMAGE_PATH"
 
 
        # 5. 移動先の絶対パスを生成
        DEST_IMAGE_PATH="$DEST_DIR/$IMAGE_FILENAME"
        echo "DEST_IMAGE_PATH = $DEST_IMAGE_PATH"
 
        # 6. 画像ファイルを移動(dry run 時は表示のみ)
        if [ "$DRY_RUN" = "true" ]; then
          echo "[Dry Run] Would move: $SOURCE_IMAGE_PATH  ->  $DEST_DIR/$IMAGE_FILENAME"
        else
          mv "$SOURCE_IMAGE_PATH" "$DEST_DIR/"
          echo "Moved: $SOURCE_IMAGE_PATH  ->  $DEST_DIR/$IMAGE_FILENAME"
        fi
 
    done
done
 
echo "Done."

これを実行後、無事に表示されるようになった。 よっしゃー deploy時にこのshell script が実行されるようにしておく

Obsidianの画像表示は、どんなディレクトリ配下であってもファイル名で表示される設計のおかげで、元のマークダウン内部の参照名は書き換える必要がなく、画像だけ移動させればいいのは楽だな。 またこういうのがシュッとできるのは、ローカルファイルで扱える Obsidianならではの長所

余談

Obsidianで ![[Pasted image 20250114115920.png]] という内容があります。 Pasted image 20250114115920.png という画像ファイル名を grep で抽出したいのですがどうすればいいでしょか?

このプロンプトで Gemeni 2.0 Flash experimental だと正規表現がうまく動かなかったが、GPT 4o mini だとさらっと動いて感動…