このページは福井県立大学の田中求之が2006年1月まで運用していた Mac のサーバ運用に関する会議室 「Web Scripter's Meeting」の記録です。情報が古くなっている可能性がありますのでご注意ください。

applescriptでの限界値を教えて下さい

発言者:yabuki
( Date Monday, March 05, 2001 18:09:32 )


いつもお世話になります。
以前にデリミタ(delimiters)の記述を使った時の限界値は
4000項目ぐらいと教えていただきました。
また、readの構文を使った時にも限界値があることを教えていただきました。
(100,000バイトぐらいは問題ないが、1,000,000バイトとかは
「Out of memory」というエラーメッセージがでる事など)


今回はフォルダ内のファイルのファイル情報(パス・ファイル名・修正日など)を
テキストに書き込むスクリプトを作成して実行したところ、同じディレクトリに
200ぐらいのファイルが存在する場合に特に問題は起こりませんでしたが、
同じディレクトリに700以上存在する場合にエラーが起こります。
(エラーメッセージは「Out of memory」です)
アプレットのメモリを51,200kに上げても同じ結果でした。
(同一階層に700以上のファイルが存在するという事も大きな問題ですが...)



書き込みの際のread文の限界値でもないみたいで、エラーが起こる記述は決まった場所です。

set theFiles to every file of thePath

every fileという記述に限界値はあるのですか?(ファイル数が299までは処理しました)
誰かご教授下さい。

田中求之 さんからのコメント
( Monday, March 05, 2001 18:52:11 )

>every fileという記述に限界値はあるのですか?

この記述自体には制限などありませんが、これは Finder によって実行される
スクリプトになっているんですよね? (そうではないと意味を持ちませんから)

ですから、Out of memory を起こしているのは、スクリプトではなくて、
Finder です。 Finder に大量のファイルを処理させようとするとエラー
がおきます。

解決方法は、もちろん Finder の割り当てメモリーを増やす(方法を知って
ますか?)というのもあるのですが、普通は、Finder に頼らない
(たとえば list folder を使うなど)ようにスクリプトを変更するのが
良いと思います。

yabuki さんからのコメント
( Monday, March 05, 2001 19:42:07 )

早いレスをいつもありがとうございます。

>解決方法は、もちろん Finder の割り当てメモリーを増やす(方法を知って
>ますか?)というのもあるのですが、普通は、Finder に頼らない
>(たとえば list folder を使うなど)ようにスクリプトを変更するのが
>良いと思います。

Finder の割り当てメモリーを増やす方法を知りません。(恥)
list folder の記述自体 を使った事がありません。(汗)
勉強不足なので自分で調べます。
また判らなくなりましたら、ご教授お願いします。

貞広正則 さんからのコメント
( Monday, March 05, 2001 20:43:35 )

始めまして、貞広といいます。

今月半ばからISDNエコノミーを使って、AFP over TCPを中心としたサーバー
を立てようと考えています。

各クライアントにフォルダ作成して、それらのフォルダをファイル共有に
しようと考えています。でも、最近の記事を読むとファイル共有はかなり
セキュリティが問題であるようなことが書かれています。

最大桁数のデタラメなIDとpasswardを埋め込んだ実行専用のアップル
スクリプトでログインをしてもらう方法ぐらいしか思いつきません。
そこで、セキュリティを確保するためにはどのような手段があるので
しょうか。548番のポートをより安全にする方法は何かあるのでしょ
うか。

クライアントは限定されていますので、ログインの際に、例えば、
クライアントのハードのMACアドレスを読みとりそれで許可・不許可
をするといったようなことは出来るのでしょうか。

サーバーソフトは今月発売されるMac OS xを考えています。

よろしくお願いします。

田中求之 さんからのコメント
( Monday, March 05, 2001 22:48:09 )

list folder というのは、MacOS 8.5 以降に標準で組み込まれるようになった
フォルダー内のファイルのリストアップを行うコマンド(実体は osax )です。

標準以外の osax を使ってもよいのでしたら、私の Tanaka's osax のように
ファイルの一覧を取り出す osax はいくつかあります。こういうのをうまく
使えば、ファイル数が多くてもうまくいきますよ。ちょうど、この週末に
この会議室のアーカイブを AppleScript で作っていましたが、1フォルダーに
4000 ぐらいのファイルが入っていても、なんなく処理できています。

yabuki さんからのコメント
( Tuesday, March 06, 2001 18:09:57 )

田中さん、list folder の記述を調べました。
この記述はフォルダ内のファイル名を得るものですよね。
(間違っていたら、またご教授願います)

私が作成したscriptはフォルダ内のファイルのファイルパスを得て、
それを元にファイル名や修正日、ファイルタイプを獲得しているものです。

こんな感じです。
set theFiles to every file of thePath -- Finderに依存する問題の記述
repeat with aFile in theFiles
  set theFilePath to aFile as string -- ファイルパスの獲得
  set theFileName to (name of aFile) as string -- ファイル名の獲得
  set theFileDate to (get modification date of aFile) -- 修正日の獲得
  set theFileType to (file type obsolete of aFile) as string -- ファイルタイプの獲得
  set theFileCreator to (creator type of aFile) as string -- クリエータの獲得
end repeat

list folder の記述で上記のような事はできますか?教えて下さい。
(ファイル名からファイルパスを獲得する?)
また、フォルダ内にあるフォルダのファイル情報を獲得する記述を
下記のようにしています。

set theFolders to every folder of thePath1
repeat with aFolder in theFolders
  DiveFolder(aFolder, Names_File, CountByte) of me -- フォルダ内のフォルダ処理
end repeat

またファイルでなくてフォルダの場合でも list folder の記述は使えますか?
くだらない質問ですいません。

野本夏俊 さんからのコメント
( Tuesday, March 06, 2001 19:06:21 )

> set theFiles to every file of thePath

これは確かにメモリーオーバーフローになるようですね。

でも、
set FileNames to name of files of theFolder as text
では問題がでません。2000以上のファイルが入ったフォルダで試したので確かです。
元々リストはメモリを食いますし、file specifier はさらにメモリを食うのかもしれません。
全要素参照をうまく使うといいですよ。

yabuki さんからのコメント
( Tuesday, March 06, 2001 20:02:06 )

>解決方法は、もちろん Finder の割り当てメモリーを増やす(方法を知って
>ますか?)

判りました。ResEditを使ってメモリを増やすのですね。
一応うまくいきました。scriptの記述の方は勉強します。

yabuki さんからのコメント
( Tuesday, March 06, 2001 20:17:44 )

いつもありがとうございます。

>set FileNames to name of files of theFolder as text

上記の記述を試してみます。
ぱっと見て、どこが違うのか判らないです。(笑)

田中求之 さんからのコメント
( Wednesday, March 07, 2001 00:10:03 )

>私が作成したscriptはフォルダ内のファイルのファイルパスを得て、
>それを元にファイル名や修正日、ファイルタイプを獲得しているものです。

まず本筋には関係ないおせっかいなコメントなのですが、せっかく Finder
でファイルの情報を Finder Object (エイリアス型だと思っても支障あり
ません)で得ておきながら、それをフルパスに変換するのは、処理の無駄で
す(ファイル情報を得る時点でフルパスから File Specification へ、わざ
わざ再変換しています)。他のコメントから察するに、AppleScript でのファ
イルの扱いに関して、理解が不十分な部分があるようですので、今一度、確
認しておくことをお勧めします。フルパスと、エイリアス型と、File
Specification と、そして Finder が扱うオブジェクトは、異なります。

で、本題に入ります。

>この記述はフォルダ内のファイル名を得るものですよね。

いいえ、違います。ファイルだけでなく、フォルダーも含まれます。

>list folder の記述で上記のような事はできますか?教えて下さい。

できます。list folder で中に入っているものの名前を得ておいて、そこか
ら info for を使ってファイルの情報を得ていきます。この場合は、フルパ
スを操作する必要があります。

こんな感じです:

set myFolder to choose folder
set theItems to list folder myFolder

set myFolderPath to myFolder as string

repeat with thisItem in theItems
  set theFilePath to (myFolderPath & thisItem)
  set myInfo to info for file theFilePath
  if not folder of myInfo then
    --- ファイルの場合に情報を得る
    set theFileDate to modification date of myInfo
    set theFileType to file type of myInfo
    set theFileCreator to file creator of myInfo
    
    --- ここで得た情報を処理する
    
  end if
  
end repeat

田中求之 さんからのコメント
( Wednesday, March 07, 2001 22:10:04 )

すみません、勘違いしてました。

>まず本筋には関係ないおせっかいなコメントなのですが、せっかく Finder
>でファイルの情報を Finder Object (エイリアス型だと思っても支障あり
>ません)で得ておきながら、それをフルパスに変換するのは、処理の無駄で

これ、私の勘違いです。ごめんなさい、偉そうなこと言って。

yabuki さんからのコメント
( Thursday, March 08, 2001 16:40:40 )

田中さん、いつもありがとうございます。
説明の中にあった通り、ファイルの扱いに関して理解が不十分でした。
(今でも不十分だと思います...)
scriptを始めた時から、ファイルのフルパスを最初に得て
それから、ファイル情報を得るのだと思いこんでいました。
(ラベルやファイル名を変更するのに必ずファイルを選択するように記述していました)
リスト型の記述を使ったscriptの動向を調べて勉強しなければなりません。
(勉強不足に尽きます)

田中さんに説明して頂いたscriptで問題なく処理しました。
それを使って every file の記述のところを list folder と
info for file に変更して処理をおこなったところ、
info for file でエラーが起こってしまいます。
ダイアログ表示で調べてみたら、myFolderPath は「●●●:×××:」と表示され
thisItem は「▲▲▲」と表示されました。しかし、(myFolderPath & thisItem) を
表示したら「●●●:×××::▲▲▲」となっていました。
なぜだか判りません。何か気づかれる事がありましたら、また教えて下さい。

下記の記述がエラーになってしまうscriptです。
on open FirstObject
---(中略)---
  repeat with thePath1 in FirstObject
        my DiveFolder(thePath1, Names_File, CountByte)
  end repeat
---(中略)---
end open

on DiveFolder(thePath1, Names_File, CountByte)
  tell application "Finder"
    set theItems to list folder thePath1
    repeat with thisItem in theItems
      set theFilePath to (thePath1 & thisItem)
      set myInfo to info for file theFilePath --- ここでエラーになってしまう
      if not folder of myInfo then
        set theFileName to thisItem
        set theFileDate to modification date of myInfo
        set theFileType to file type of myInfo
        set theFileCreator to creator type of myInfo
  ---(得た情報を処理する記述)---
      end if
    end repeat
    
    set theFolders to every folder of thePath1
    repeat with aFolder in theFolders
    ---(得た情報を処理する記述)---
      DiveFolder(aFolder, Names_File, CountByte) of me
    end repeat
  end tell
end DiveFolder

yabuki さんからのコメント
( Thursday, March 08, 2001 17:40:50 )

自己レスです。
info for file でのエラーの内容はディレクトリの階層が違っているためでした。
例えばデスクトップにフォルダAがあり、その中にファイルBがあったとします。
myFolderPath は HD:Desktop Folder:A:となり、thisItem は B なります。
しかし、set myInfo to info for file (myFolderPath & thisItem) の
ファイルパスはHD:Desktop Folder:A:Bではなくて、HD:Desktop Folder:B と
なっていたからファイルが見つからないというエラーになってしまったのです。
どうして(myFolderPath & thisItem) が HD:Desktop Folder:Bになってしまうのか
調べてみます。

野本夏俊 さんからのコメント
( Friday, March 09, 2001 18:12:02 )

thePath1 はテキストではなく alias オブジェクトです。(あるいはobject specifier)ファイルパスとは別物なので、それなりの扱いが必要です。

file ... で参照できるのはファイルだけです。
フォルダはaliasオブジェクトとして渡す必要があります。

yabuki さんからのコメント
( Thursday, March 22, 2001 18:40:08 )

レスが遅くなってすいませんでした。
ようやく list folder を使った記述でうまく処理できました。

これも田中さんと野本さんの助言があったからです。
ありがとうございました。