10倍速Finder処理

1998.01.27

by 野本夏俊


●フィルタを使おう

 Finderでのフィルタの使い方はあまり紹介されていないので、使ったことがある方は割と少ないと思います。
 ぼく自身も使ったのは今回が初めてですが、あまりの効果に感動してしまいました。
 フィルタは使い方にクセがあるので(といってもそのクセを完全に修得しているわけではありませんが...)取っ付きにくいことは否定できませんが、スクリプトの速度アップには使いようによっては絶大な効果があります。

 たとえば、ある条件にあったファイルのクリエータとファイルタイプを変更したい場合に、普通に考えると、以下のようなスクリプトを組むと思います。(実際にぼくが使っていたものです)

 [--強制改行]の部分は半角の「ツ」(option-return)に変えてください

property CT : "MOSS"
property FT : "TEXT"

my PrePro()

on open
  my PrePro()
end open

on PrePro()
  tell application "Finder"
    my MOSS(selection)
  end tell
end PrePro

on MOSS(x)
  tell application "Finder"
    repeat with i in x
      try
        set ItCl to class of i
        if ItCl = document file then
          set N to name of i
          if (N ends with ".gif") or (N ends with ".html") or --強制改行
            (N ends with ".jpg") or (N ends with ".htm") or --強制改行
            (N ends with ".jpeg") then
            set {creator type of i, file type of i, icon of i} to {CT, FT, {}}
          end if
        else
          if ItCl = folder then
            my MOSS(every item of i)
          end if
        end if
      on error
      end try
   end repeat
  end tell
end MOSS

 PrePro()の処理の部分は好みもあるでしょうが、ぼくは、あとで alias.....を使うよりはこのほうがすきです。
このなかのon PrePro()〜end MOSSをフィルタを使った方式にすると以下のようになります。

on PrePro()
  tell application "Finder"
    try
      tell (document files of selection whose ((name ends with ".gif") or --強制改行
        (name ends with ".html") or (name ends with ".jpg") or --強制改行
        (name ends with ".htm") or (name ends with ".jpeg")))
        set file type to FT
        set creator type to CT
        set icon to {}
      end tell
    on error
    end try
    try
      my MOSS(folders of selection)
    on error
    end try
  end tell
end PrePro

on MOSS(x)
  tell application "Finder"
    repeat with i in x
      try
        tell (document files of i whose ((name ends with ".gif") or --強制改行
          (name ends with ".html") or (name ends with ".jpg") or --強制改行
          (name ends with ".htm") or (name ends with ".jpeg")))
          set creator type to CT
          set file type to FT
          set icon to {}
        end tell
      on error
      end try
      try
        my MOSS(folders of i)
      on error
      end try
    end repeat
  end tell
end MOSS

 ちょっと長いですね。ポイントは2つあります。

  1. フィルタを使って条件にあったオブジェクトを特定していること
  2. tellを使って複数のオブジェクトに同時に命令を送っていること
 です。

 コツとしては、何と説明していいのかよくわかりませんが、常に完全参照(たぶん)を得られるように工夫する、 ということだと思います。一度変数に入ってしまったものにはフィルタもtell〜も使えません。上の例でもMOSS()に送るパラメーターをフォルダに限定することで完全参照を得る工夫をしています。1番目のスクリプトと2番目のスクリプトでは2番目のほうが10倍(!!!)位高速です。

 ちなみにこちらのサイトでダウンロードできる「AppleScript Online Manual」を2番目のアプレットにドロップすると、22秒で処理しました(OS7.6.1 AppleScriptJ1-1.1.1 UMAX Pulsar2250) 1番目のものでは179秒かかりました。ディレクトリ構造が簡単でファイル数の多い場合はさらに差が広がると思います。

 フィルタにはケースバイケースでさまざまな工夫が必要になってくると思います。皆さんもぜひ試して見てこういうケースではこのようにすればいいぞなどのノウハウを公開していただけると嬉しいです。(野本)

”補足”--

 階層をたどっていく処理が必要ない場合には(そうしたいときにはアウトライン表示を使う)MOSS()以降は必要なくなり、さらに高速化します。

 実際には、以下のようになります。

on PrePro()
  tell application "Finder"
    try
      tell (document files of selection whose ((name ends with ".gif") or --強制改行
        (name ends with ".html") or (name ends with ".jpg") or --強制改行
        (name ends with ".htm") or (name ends with ".jpeg")))
        set file type to FT
        set creator type to CT
        set icon to {}
      end tell
    on error
    end try
  end tell
end PrePro

 アウトラインで展開したものをドロップしたときにはかえって遅くなるだけなのでこのほうがいいかもしれません。(野本)

”補足2”--

 読んでいて気が付いたのですが,

on open
  my PrePro()
end open

 では,Finder上で目標のファイルまたはフォルダが選択されていることが条件ですが,ヘルパーとしてNetscapeやEudoraPro,Anarchieなどのソフトウエアから呼び出されるように設計されているソフト(私のところにはそういうのが多いんです)ではFinder上で選択されずに直接AppleScriptにopenコマンドが送信されます。そのような場合にも利用できるように一部分を修正してみました。

on open (FileList)
  tell application "Finder" to set selection to FileList as list
  my PrePro()
end open

 これなら,野本さんの高速なルーチンを利用することができ,かつヘルパーアプリケーションとしてもFinderを経由せずに利用できます。(鈴木)


Tipsに戻る
AppleScriptのページに戻る
このホームページに関するお問い合わせは、karino@drycarbon.comまで。