mattintosh note

どこかのエンジニアモドキの備忘録

Finder で選択した複数のディレクトリを個別に ZIP にする

Finder では複数の選択項目をひとつのアーカイブにすることはできても、個別にアーカイブ化することができないので Automator でアプリケーションを作ってみた。日付別なんかで JPEG イメージが保存されたディレクトリを個別に ZIP 化するのが目的。

ファイルの圧縮を追加すると掃除処理の際に色々と面倒になるのでディレクトリ専用。圧縮後はディレクトリを自動でゴミ箱へ送る。Finder のツールバーに置いて使うのでシェルスクリプトアクションの前に「選択された Finder 項目を取得」を追加して「入力を無視」にしておく(ドラッグ入力だと操作に不安があるので)。

# mode: stdin

while read
do
    [ -d "$REPLY" ] && cd "${REPLY%/*}" || continue
    REPLY="${REPLY##*/}"
    zip -0 -r "$REPLY".zip "$REPLY" -x "*/.DS_Store" "*/Thumbs.db" && {
        mv "$REPLY" $HOME/.Trash || mv "$REPLY" $HOME/.Trash/"$REPLY `date +%H-%M-%S`"
    } || exit 1
done
afplay /System/Library/Sounds/Hero.aiff


Automator のアクションは重かったりバグがあったりするのでフィルタリングはシェルスクリプト内で行う。入力がディレクトリ以外の場合はループを飛ばす。zip コマンドは tar コマンドと同様に入力にフルパスを指定するとそのままアーカイブしてしまうので cd させておく。

[ -d "$REPLY" ] && cd "${REPLY%/*}" || continue


cd 後はフルパスで扱うことはないので相対パスにしておく。(以下は basename と同様)

REPLY="${REPLY##*/}"


扱うファイルによるけど JPEG なんかは ZIP で圧縮しても大して効果はないので圧縮レベルは 0(ゼロ)。.DS_Store も要らないので -x "*/.DS_Store" で圧縮対象から除外する(-x \*/.DS_Store という書き方もある)。Windows からコピーしてきたフォルダだと Thumbs.db が入っていたりするのでこれも除外。

zip -0 -r "$REPLY".zip "$REPLY" -x "*/.DS_Store" "*/Thumbs.db"


手動でフォルダを削除するのが面倒なので圧縮後はゴミ箱に送るようにする。GNU 版の mvgmv)にはバックアップオプションがあるのでゴミ箱に同名のフォルダが存在する場合はリネームしてくれるけど、Mac OS に入っている BSD 版の mv では使えないのでデフォルトの名前で mv に失敗したら HH-MM-SS を付加するようにしておく。

mv "$REPLY" $HOME/.Trash || mv "$REPLY" $HOME/.Trash/"$REPLY `date +%H-%M-%S`"


圧縮対象が大量にあるといつ終わったかわかりづらいので afplay でサウンドを再生するようにしておく。

afplay /System/Library/Sounds/Hero.aiff


このアプリケーションを Finder のツールバーに配置しておけばディレクトリ選択後にワンクリックで個別 ZIP 化ができる。


追記(2013-01-15)

ゴミ箱のクリーニングが面倒になってきたのでちょっと書き換えてみた。

オプションに -m or --move を指定すると既存のファイルをアーカイブ内に移動してくれる(つまり元のファイルがなくなる)ので削除する手間が省ける(処理も少し早くなる?)。除外指定などでファイルが残っている場合、元のディレクトリは削除されない。元ファイルの重要性が高い場合はおすすめしません。

-b or --temp-path を使うと一時ファイルの作成場所を指定できる。ファイル監視が有効になっているディレクトリ(例えば Dropbox など)の場合は一時ファイルのためにいちいち更新処理が発生するのが無駄なので /tmp あたりに変更しておくといいかも。

# mode: stdin

while read f
do
    [ ! -d "$f" ] && continue
    cd "${f%/*}"
    zip -0mr -b /tmp "${f##*/}".zip "${f##*/}" -x "*/.DS_Store" "*/Thumbs.db"
done