Photoshopを開かずに画像を一括変換するCLIの作り方

2026.08.11 09:00
2026.08.30 00:36
Photoshopを開かずに画像を一括変換するCLIの作り方

Webサイト用の画像が増えるたびにPhotoshopを開き、1枚ずつWebPへ書き出すのは地味に時間がかかります。そこで案件ごとに変換スクリプトを書いてきたのですが、原本を消したり、サブディレクトリを見落としたりと、毎回違うところで失敗しました。

何度か作り直して、いまは再帰検索、アイコン除外、成功確認、原本退避をひとまとまりの仕様として扱っています。単に変換コマンドを呼ぶだけでは足りなかった理由を、順番に整理します。

原本を削除しない

変換後のPNGやJPEGを削除すると、後日の修正に対応できません。public/ の外にあり、Git管理される場所へ移動します。

mv "$f" "assets/images/${rel}"

退避先が変換対象内だと再変換されるので注意します。faviconやPWAアイコンも除外します。

case "$(basename "$f")" in
  favicon*|icon-*|apple-touch-icon*|apple-icon*) continue ;;
esac

サブディレクトリも対象にする

find "$PUBLIC_DIR" -type f \( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' \) -print0 |
while IFS= read -r -d '' f; do
  # 変換処理
done

変換コマンドの成功と出力ファイルの両方を確認してから原本を動かします。

if npx sharp-cli -i "$f" -o "$out" >/dev/null 2>&1 && [[ -s "$out" ]]; then
  mv "$f" "$archive"
else
  echo "変換失敗のためスキップ: $f" >&2
fi

自動実行する場所を選ぶ

エディタのフックはAIが編集した場合しか発火せず、人がFinderやscpで追加した画像を拾えません。編集のたびに外部通信を伴う npx が走る問題もあります。手動実行か、ホスト側のデプロイスクリプトで1回だけ実行するほうが安定します。

img_src/ から img/ を生成する構成では、入力から削除した画像が出力に残る場合があります。入力と出力のbasename集合を比較し、出力側だけにある孤児を検出します。mtimeはclone時に変わるので、更新判定にはハッシュを使います。

ここまで入れて、ようやく「画像を変換するコマンド」ではなく、普段の制作で安心して使える道具になりました。変換品質だけでなく、失敗時に原本が残ること、削除が出力へ伝わること、誰が画像を置いても同じ経路を通ることまでがCLIの仕様です。

最後に見るべきなのは、手元で動いたかではなく、実際のデプロイ経路から呼ばれているかどうかです。ローカルだけで完成していた自動化を何度か作ったので、いまはそこまで確認して終わりにしています。

今回は以上です。