AppleScript Automator Mac シェルコマンド シェルスクリプト プログラミング

フォルダ内の画像・動画をブラウザ上で一覧できるシェルスクリプト&Automatorアプリ

PCでたくさんの画像の見るのって意外と面倒

仕事でスクリーンショットをたくさん撮りました。

撮った画像とファイル名を見ながらテキストを書く作業をしていたのですが、これが結構面倒くさいんですね。

MacのFinderのQuickLookで1枚ずつ見るのは大変です。Adobe Bridgeも悪くはないのですが、ちょっと機能が多すぎますし縮小画像しか見られないのが不便。

というわけで、Webブラウザで見られるようなアプリを作りました。

Automatorアプリになっていて、Finderのツールバーにセットして使います。

アプリを起動したフォルダに含まれる画像ファイルの一覧をファイル名付きでブラウザに表示します。

やっていることは単純で、フォルダ内の画像ファイル名を抽出して、HTML内のimgタグに設定して書き出しているだけです。

Webブラウザでの閲覧は軽快でいいです。

ファイル名は大きくして老眼でも見やすくしています。

思った以上に便利だったので動画も処理対象にしたほか、表示サイズをワンタッチ("1"キー)で切り替えられるようにしました。

1キーを押す度に画像サイズがブラウザの幅一杯と半分で切り替わります。

利用にはnkfが必要です。ファイル名をURIエンコードするのに使っています。

私はhomebrewでインストールしました。

brew install nkf

Automatorアプリの中身

Automatorアプリは二段構成です。

1段目はAppleScriptで現在のフォルダをパスとして取得します。

2段目のシェルスクリプトでHTMLファイルを作ります。

シェルはなぜかbashじゃないと動きません。

AutomatorのAppleScript部分

これは現在のフォルダーを取得するAppleScriptです。よく使うお決まりのパターンです。

アプリをFinderのツールバーに設定しておくと、起動したウインドウが表示しているパスを取得できます。

tell application "Finder"
	
	set current_folder to POSIX path of (target of front window as alias)
	
end tell
return current_folder

Automatorのシェルスクリプト部分

lsコマンドで前段から受け取ったパスのファイルリストを取得します。

まずhtmlヘッダとスタイルシートをファイルに出力

grepで画像と動画形式だけに絞って、listという変数に入れます。

for文でlistの中身を一行ずつ取り出します。

sedで拡張子を取り出してextという変数に入れます。

ファイル名をh1タグで囲んでファイル出力します。

拡張子によって、imageタグかvideoタグで囲んでファイルに出力します。

ループから抜けたらJavascriptと締めhtmlをファイルに書き込みます。

Javascriptは、表示サイズの切り替え機能を実装しています。

キーボードの"1"キーを押すと、画像サイズがウインドウ幅の1/2になります。再度1を押すと元の100%に戻ります。CSS変数をJavascriptで書き換えています。

ウインドウ幅を小さくしてから1/2表示にし、ウインドウを拡げるとより多くの画像を一度に見られます。

画像はimgタグではりつけているので、ドラッグ&ドロップでFinderにダウンロードしたり、右クリックで別窓で開いたりできます。

シェルはbashを指定してください。

mac側ではzshをデフォルトシェルにしているので、nkfをインストールしてもパスが通っていません。

このため、nkfはフルパスで起動しています。

output_file=$1picture_list.html

echo '<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>media gallery</title>
</head>
<body>
  <style>
    :root {
      --samnail-width: 100%;
    }

    .fileName {
      font-size: 200%;
      text-align: center;
      display: block;
    }

    .box {
      display: inline-block;
      width: 100%;
    }

    .small {
      width: var(--samnail-width);
    }

    img {
      display: block;
      width: 100%;
    }

    video {
      display: block;
      width: 100%;
    }

  </style>
  <p>press "1" key to change element size</p>' >$output_file

list=$(ls $1 | grep -e ".png" -e ".jpg" -e ".PNG" -e ".JPG" -e ".mp4" -e ".MP4" -e ".mov" -e ".MOV" -e ".jpeg" -e ".JPEG")

IFS=$'\n'
for line in $list; do
  ext=$(echo $line | sed 's/^.*\.\([^\.]*\)$/\1/')
  uri='"'$(echo $line | /opt/homebrew/bin/nkf -WwMQ | sed 's/=$//g' | tr = % | tr -d '\n')'"'
  echo '<div class="box"><h1 class="fileName">'$line'</h1>' >>$output_file

  case "$ext" in
  "png" | "jpg" | "jpeg" | "PNG" | "JPG" | "JPEG")
    echo '<img src='$uri'></div>' >>$output_file
    ;;
  "mov" | "mp4" | "MOV" | "MP4")
    echo '<video src='$uri' controls ></div>' >>$output_file
    ;;
  *)
    :
    ;;
  esac
done
echo '
<script>
    window.addEventListener("keyup", function (e) {
      console.log("pressed:", e.key);
      const elems = document.querySelectorAll(".box");
      if (e.key == "1") {
        const samnailWidth = parseInt(document.body.clientWidth / 2 - 15);
        document.documentElement.style.setProperty("--samnail-width", samnailWidth + "px");
        elems.forEach((elm) => {
          elm.classList.toggle("small");
        });
      }
    });
</script>
</body>
</html>' >> $output_file
open $output_file

Finderと同じ順番で並べたいので別バージョンも作った

このAutomatorアプリはたいへん便利なのですが、ひとつ欠点があります。

連番ファイルがあったとき、例えば1、10、100、109、11、110という順番にならんでしまいます。

Finderの表示機能はかなり賢くソートしてくれるのですが、同じソートをスクリプトで実現する方法が分かりません。

そこで、Finder上でファイル名をコピーしてから起動するバージョンも作りました。

あらかじめFinder上でファイルを選択し、編集メニューのコピーを選びます。

Automatorアプリを起動すると、Finderと同じ順番で画像一覧が作成されます。

やっていることは単純で、lsの代わりにpbpasteコマンドを使ってファイル名を取得しています。

拡張子による選別も行っているので、とりあえずフォルダ内を全選択&コピーしてから起動しても構いません。

とにかくさくっと一覧したい時にはlsバージョン、並びにこだわる場合にはpbpasteバージョンと使い分けるとよいでしょう。

pbpaste版のコード

違いはシェルスクリプト部分だけです。

lsコマンドをpbpasteに変えたほか、改行コードの統一を行っています。

ターミナルから使うシェルスクリプト版を作れば、オプションの有無てlsかpbpasteかを選択するようにもできると思います。

また、下位の階層のファイルも含めて一覧したい場合にはfindコマンドを使えばできるはすです。

output_file=$1picture_list.html

echo '<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>media gallery</title>
</head>
<body>
  <style>
    :root {
      --samnail-width: 100%;
    }

    .fileName {
      font-size: 200%;
      text-align: center;
      display: block;
    }

    .box {
      display: inline-block;
      width: 100%;
    }

    .small {
      width: var(--samnail-width);
    }

    img {
      display: block;
      width: 100%;
    }

    video {
      display: block;
      width: 100%;
    }

  </style>
  <p>press "1" key to change element size</p>' >$output_file

list=$(pbpaste | sed -e "s/\r/\n/g" | grep -e ".png" -e ".jpg" -e ".PNG" -e ".JPG" -e ".mp4" -e ".MP4" -e ".mov" -e ".MOV")

IFS=$'\n'
for line in $list; do
  ext=$(echo $line | sed 's/^.*\.\([^\.]*\)$/\1/')
  uri='"'$(echo $line | /opt/homebrew/bin/nkf -WwMQ | sed 's/=$//g' | tr = % | tr -d '\n')'"'
  echo '<div class="box"><h1 class="fileName">'$line'</h1>' >>$output_file

  case "$ext" in
  "png" | "jpg" | "PNG" | "JPG" | "JPEG")
    echo '<img src='$uri'></div>' >>$output_file
    ;;
  "mov" | "mp4" | "MOV" | "MP4")
    echo '<video src='$uri' controls ></div>' >>$output_file
    ;;
  *)
    :
    ;;
  esac
done
echo '
<script>
    window.addEventListener("keyup", function (e) {
      console.log("pressed:", e.key);
      const elems = document.querySelectorAll(".box");
      if (e.key == "1") {
        const samnailWidth = parseInt(document.body.clientWidth / 2 - 15);
        document.documentElement.style.setProperty("--samnail-width", samnailWidth + "px");
        elems.forEach((elm) => {
          elm.classList.toggle("small");
        });
      }
    });
</script>
</body>
</html>' >>$output_file
open $output_file

-AppleScript, Automator, Mac, シェルコマンド, シェルスクリプト, プログラミング