見出し画像

ZIPでファイル圧縮をしよう! 【5】

さて、このお題も最終章といきたい、と書き始めるも、すでにあれから2ヶ月が経ち…
いいかげんに自分でもちゃんと使えるものにしないといけません。前回はこちら。

前回の終わりで、アクション全体が長くなるから AppleScript で全部やってしまおうというような話をしましたが、パスを分解し格納したそれぞれの変数はそのまま持っておいた方がいいですね。

そのうえで…

「origFullPath(オリジナルのパス全体)」、
「origPath(オリジナルのパス部分のみ)」、
「origFileName(オリジナルのファイル名部分のみ)」、
と、3つの変数を作成したわけですが、これらを一気に AppleScript(「AppleScriptを実行」アクション)に渡す方法について調べていました。私も get/set については初心者ですので!

しかしそれは簡単であることが判明しました。
「変数の値を取得」を、ただ繋げて並べて流し込めばいいのです!

ここで画像で全てをお見せしておきましょう。
上の変数の定義・代入の後は、処理が一旦途切れてもかまわないので、そのようになっていて、画像はその直後からです。

いつか見てもらったように、「AppleScriptを実行」アクションでは「on run〜」の関数ブロックの中で処理を記述します。

説明しやすいように、その中を5つの段落に分けました。順番にみていきましょう。


① 渡された3つの変数を再格納


まずは、 input 引数に落ちてきた3つの変数の値を、新たにこのブロック内で使いやすいように変数に格納しています。

先に書きましたとおり、こんな風に変数をずらずらと並べて一気に送り込むと、「AppleScriptを実行」アクションの側では、「item x of input〜」のようにして、配列のようにして取り出せます。なんと単純な仕様でしょうか。笑

対応関係を見ていただくと(実際にやってみていただくと)、順番も保持されていますので、適切に変数の名前を決めてそれぞれを格納します。
「item x of input〜」のまま使うことももちろんできるのですが、冗長だしわかりにくいですからね。

おっとここで「POSIX path」について説明しなければなりません。
Macintosh の OS の上でのローカルなパス表現(パス区切り)は、コロン(:)なんですね。それは OSX になるまでの話なんですが、内部的には互換性のためか面倒な変換がされているらしく、今回突っ込みません。笑

それを、シェルで使えるように UNIX の標準パス区切り文字であるスラッシュ(「/」)に変換してくれるのがコレなのです。AppleScript の言語仕様として用意されています。パス関連で何かエラーが起きたらとりあえずこれを疑ってみていいかも。

② シェルにZIPさせるためのパスを連結作成

set output_filename to filename_str & ".zip"
set output_dirname to "dir_output.zip"
set input_file to path_str & filename_str
set output_file to path_str & output_filename
set output_dir to path_str & output_dirname

この塊では、割と単純なパスの組み立てをしています。
アンパサンド(「&」)は、文字列を連結するのに使います。上で「POSIX path〜」によって変換したそれに基づいて記述していますが、わかりますかね?

最初は、オリジナルのファイル名を拡張子とさらに分解して、なんて思ってましたが、結局面倒になってやめたという 笑

③ ZIPコマンドのための用意

1行目は、基本的なコマンド名を。
2行目では、コマンドのオプション部分を。

オプション部分は後でどのみち追加が発生するので、何も入っていない箱だけ用意しておいたということです。

こういう、コマンドの文字列全体を組み上げるときに気をつけなければならないのは、区切りとなる半角スペースですね。これがないと当然動作しませんし、私自身いつもこんがらがります。

set zipcmd to "zip "
set zipcmd_opts to ""
set file_test to do shell script "test -f " & orig_path_str & " ; echo $?"

3行めについてなのですが

勘のいい方はお気づきだったと思います。
ファイルの種類の判別・判定が必要だということを。圧縮は、単体ファイルとフォルダ、それぞれにできるというのが一般的ですからね。

ここでは簡易的に、単ファイルかどうか調べ、そうでないものはフォルダであるという処理にします。おそらくそれで、実際には支障のない動作になるのではないかと。そしてそこでもシェルが活躍します。
AppleScript の「do shell script」命令、これは本当に便利で、相互にやりとりを可能にするいち手段となっています。

test -f <判定対象のファイル> ; echo $?

シェルでこのように test コマンドを使うと、これまた1行で対象がファイルであるかどうかが得られます。
セミコロンは、左側のコマンドつまり test がどういう終了をしようと連結された右のコマンドが実行されるというもので、先に紹介した「|」パイプの一種です。 つまりこれによって、真であるか偽であるか、双方の結果が変数「$?」に格納されることになり、それを echo で取り出している、というわけです。

ややこしいのは、この場合、test が正常な終了をした場合、つまり単ファイルであった場合に「0」(ゼロ)という値が返ってくるということです。笑

普通、真偽判定をしたい場合、"1が真、0が偽" とするのが一般的だと思うのですが、そのへんは臨機応変に… 実際私は何度もテストを繰り返しました。笑

さらにややこしかったのは、これは数値でなくて文字列だということでしたが、ともかくその結果を「file_test」という変数に格納しつつ、次の段落へ進むことになります。

④ ファイルテストに基づく操作

制御構文、というのは説明したことがありましたっけ。
ここでは、「この場合はこの操作、そうでない場合はこの操作」という条件分岐をする「if 文」を使っています。

if file_test is "0" then

          set zipcmd_opts to "-j " & output_file & " " & input_file

else

           set zipcmd_opts to "-rj " & output_dir & " " & orig_path_str

end if

if 文の書式も、プログラミング言語により色々とありますが、AppleScript ではこうなります。
「if 〜 end if」までが制御の区切りで、その中に else 節を、必要な分岐条件の数だけ配置します。

test コマンドの結果、つまり対象がファイルであるかフォルダであるか、今回はその2つの場合しか存在しないのでこのような簡単な記述になりました。
またそれにより、zip コマンドのオプション部分の記述が変化しますので、振り分けて組み立てています。ここでようやく、空の変数「zipcmd_opts」の中が埋まるというわけ。

⑤ 準備完了、いざ ZIP

do shell script (zipcmd & zipcmd_opts)

変数「zipcmd」と「zipcmd_opts」の中身が、これで出揃ったということで、最後にふたたび「do shell script」命令でこの二つを連結しながらシェルに zip 操作をさせます。


おつかれさまでした

長くダラダラと続いた(続いてしまった)このシリーズもこれで完結。今のところはきちんと動いています。

残っている問題の一つは、パスワード付きZIPをどうするかということなのですが、シェルには「zipcloak」という、後付けでzipファイルに対してパスワードを設定できるコマンドが存在しているので、それを使ってもいいかもしれません。

もう一つの問題は、調べていくうちに、シェルの zip でも結局、フォルダを圧縮した場合に、中に不要な隠しファイルが入ってしまうということ。
なんだよそういうことかよ〜なんて思いましたが、一応これも解決策はありまして

zip -rj <圧縮後ファイル> <圧縮前ファイル> -x "*.DS_Store" "*__MACOSX*"

このようなことをすると一応はクリーンな?圧縮ファイルとなりそうなのですが、ちょっと調べるとこういうのは沢山出てくるので興味があれば。


前提として、ZIP圧縮などをして他者、他OSとファイルをやりとりする場合は、ファイル(フォルダ)名称に日本語を使っちゃなりません。
私は普段からファイルの命名に、可能な限り日本語、2バイト文字を使わない癖がつきました。


さてこのシリーズ、簡単な機能の実現ではあったのですが、組みながら調べを繰り返すうちに非常に多くの学びがありました。皆様にとってもそうであったら幸いです。ではまた!


この記事が気に入ったらサポートをしてみませんか?