Archive for the '並列処理(Parallel Processing)' Category

2017/10/16 並列ダウンロードのじっけん v2

AppleScriptによる狂気のthreadごっこ。並列ダウンロードの実験AppleScriptです。

昨日のScriptを実際に何度も実行してみて「Threadを生成しても順次実行されているようにしか見えないのはなぜだろう?」などと思いつつ、スレッドのオブジェクトを配列に突っ込んでおいて、一括で実行命令(start:)を行うように改良してみました。

また、スレッド内で実行する内容に単なるカウントという(安全ではあるものの)無意味な処理ではなく、ファイルのダウンロード実行を行なっています。

自分的にはいろいろとブレークスルーな内容ではあるものの、ダウンロードにしてもThread処理するよりも逐次実行したほうが速そうな感じであるのと、shellのcurlコマンドで並列でダウンロードしたほうが安全で速そうとか、かなり「不可能にチャレンジした以外にあまりほめるべき点がない」という雰囲気になっています。

AppleScript名:並列ダウンロードのじっけん v2
– Created 2015-08-20 by Takaaki Naganoya
– Created 2017-10-16 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4898

property aProp : {}
property aMax : {}

set aList to {“http://piyocast.com/as/wp-content/uploads/2016/08/xbook1_ver2.png.pagespeed.ic.1UE9W7-aVC.png”, “http://piyocast.com/as/wp-content/uploads/2016/08/xbook2_v2.png.pagespeed.ic.uWjZsXaLOP.png”, “http://piyocast.com/as/wp-content/uploads/2016/09/xscript_assistant.jpg.pagespeed.ic.fk8YHumFYV.jpg”}

set aProp to {}
set thList to current application’s NSMutableArray’s new()
set aMax to length of aList
set aCount to 1

repeat with i in aList
  set j to contents of i
  
set aURL to (current application’s |NSURL|’s URLWithString:j)
  
set aThread to (current application’s NSThread’s alloc()’s initWithTarget:me selector:“_threadLoop:” object:aURL)
  (
aThread’s setName:(“thread “ & (aCount as string)))
  (
thList’s addObject:aThread)
  
  
set noter1 to current application’s NSNotificationCenter’s defaultCenter()
  (
noter1’s addObserver:me selector:“_threadWillExit:” |name|:(current application’s NSThreadWillExitNotification) object:(thList’s lastObject()))
  
  
set aThread to “” –purge object from memory
  
set aCount to aCount + 1
end repeat

thList’s makeObjectsPerformSelector:“start” withObject:0

repeat 100000 times
  if length of aProp aMax then exit repeat
  
delay “0.0001″ as real
end repeat

–各Threadが実行するハンドラ
on _threadLoop:aInfo
  checkURLResourceExistence(aInfo, 10) of me
end _threadLoop:

–Threadが終了する際に呼ばれるハンドラ
on _threadWillExit:aNotification
  set tmpRes to aNotification’s object’s |name|()
  
log tmpRes as string
end _threadWillExit:

– 指定URLにファイル(画像など)が存在するかチェック
–> {存在確認結果(boolean), レスポンスヘッダー(NSDictionary), データ(NSData)}
on checkURLResourceExistence(aURL, timeOutSec as real)
  set aRequest to (current application’s NSURLRequest’s requestWithURL:aURL cachePolicy:(current application’s NSURLRequestUseProtocolCachePolicy) timeoutInterval:timeOutSec)
  
set aRes to (current application’s NSURLConnection’s sendSynchronousRequest:aRequest returningResponse:(reference) |error|:(missing value))
  
set dRes to (first item of (aRes as list))
  
set bRes to (second item of (aRes as list))
  
if bRes is not equal to missing value then
    set hRes to (bRes’s allHeaderFields())
    
set aResCode to (bRes’s statusCode()) as integer
  else
    set hRes to {}
    
set aResCode to -1 –error
  end if
  
set the end of aProp to {(aResCode = 200), hRes, dRes}
end checkURLResourceExistence

★Click Here to Open This Script 

2015/07/27 on idleハンドラで1秒以下の間隔でタイマー割り込み処理を行う

現在ではAppleScriptObjCを使うと普通にできる処理ですが、「0.1秒間隔でのタイマー割り込み処理をやりたい、Mac OS X 10.5上で」という質問を見かけ、その場で思いついたのがこの方法です。

1秒間隔でbeep音を鳴らすアプレットを書く。

AppleScript名:on_idle_sample
on run
  
end run

on idle
  tell current application
    beep
  end tell
  
return 1
end idle

★Click Here to Open This Script 

デスクトップ上に1.app〜9.appまでアプリケーション書き出し or アプリケーションとして保存しておく。

on_idle.png

起動用Scriptがこちら。0.1秒間間隔で上記のアプレットを順次起動する。

AppleScript名:sub_second_idle_applet_launcher
set dtPath to POSIX path of (path to desktop)

repeat with i from 1 to 9
  
  
set aPath to dtPath & (i as string) & “.app”
  
do shell script “open “ & aPath
  
do shell script “sleep 0.1″
  
end repeat

★Click Here to Open This Script 

終了用Scriptがこちら。正確に0.1秒間隔かはわかりませんが、1秒よりも短い間隔でbeep音が鳴ります。つまり、beep処理を行っているところで本来の処理を行えばよいでしょう。アプレットの動的生成による並列処理で培った(無駄な)ノウハウが生きています。

日本の戦国時代には、「長篠の戦い」という有名な(&最近は本当にあった出来事なのか疑問視されていますが)戦いがあり、撃つのに時間がかかる当時の鉄砲を、3交代で撃つことで3倍の速射ができたよ、という出来事を参考にしているものです。

AppleScript名:sub_second_idle_applet_quter
set dtPath to POSIX path of (path to desktop)

repeat with i from 1 to 9
  
  
set aPath to dtPath & (i as string) & “.app”
  
tell application aPath to quit
  
end repeat

★Click Here to Open This Script 

2014/12/11 NSSoundで音声を再生 v2

NSSoundで音声を再生するAppleScriptのバージョンアップ版です。

警告音のNSSoundオブジェクトをlistに入れ、NSArrayに変換したあとで一斉にplay()のメッセージを送って再生させています。

この件に関して、やりたいと思っていた処理がだいたいできました。

AppleScript名:NSSoundで音声を再生 v2
– Created 2014-12-11 by Takaaki Naganoya
– 2014 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “ASObjCExtras”
use framework “AppKit”

set aList to {“Basso”, “Blow”, “Bottle”, “Frog”, “Funk”, “Glass”, “Hero”, “Morse”, “Ping”, “Pop”, “Purr”, “Sosumi”, “Submarine”, “Tink”}

set sList to {}
repeat with i in aList
  set j to contents of i
  
set aSound to (current application’s NSSound’s soundNamed:j)
  
set the end of sList to aSound
end repeat

set aArray to current application’s SMSFord’s Cocoaify:sList

aArray’s makeObjectsPerformSelector:“play” withObject:0

★Click Here to Open This Script 

2011/07/06 指定のデジカメ画像のExif情報から指定のプロパティを取得する

指定のデジカメ画像のExif情報から指定のプロパティを取得するAppleScriptです。

デジカメ画像のExif情報を取得する場合には、Image Events経由でアクセスすることになりますが……実際に使ってみると、クラッシュしまくるImage Events。AppleScriptの実行をApple純正のアプリケーションが阻害するというあり得ない現象が頻発。

そこで、Image Eventsをアテにしないで、sipsコマンドをAppleScriptから呼び出すことにしてみました。Image Eventsはsipsを呼び出しているAS用インタフェース・アプリケーションですが、この調子ではAppleScriptによる並列処理などを考えるとsipsをダイレクトに呼び出した方がご利益が大きそうです。

指定できるプロパティ値については、Terminal上でsipsコマンドのhelpを見て確認してください。

Special property keys:
all binary data
allxml binary data

Image property keys:
dpiHeight float
dpiWidth float
pixelHeight integer (read-only)
pixelWidth integer (read-only)
typeIdentifier string (read-only)
format string jpeg | tiff | png | gif | jp2 | pict | bmp | qtif | psd | sgi | tga
formatOptions string default | [low|normal|high|best| ] | [lzw|packbits]
space string (read-only)
samplesPerPixel integer (read-only)
bitsPerSample integer (read-only)
creation string (read-only)
make string
model string
software string (read-only)
description string
copyright string
artist string
profile binary data
hasAlpha boolean (read-only)

Profile property keys:
description utf8 string
size integer (read-only)
cmm string
version string
class string (read-only)
space string (read-only)
pcs string (read-only)
creation string
platform string
quality string normal | draft | best
deviceManufacturer string
deviceModel integer
deviceAttributes0 integer
deviceAttributes1 integer
renderingIntent string perceptual | relative | saturation | absolute
creator string
copyright string
md5 string (read-only)

スクリプト名:retExifAttributeData v2
set aFile to choose file
set aRes to retExifAttributeData(aFile, “model”) of me
–> “GR Digital “

set bRes to retExifAttributeData(aFile, “formatOptions”) of me
–> “default”

–SIPSコマンドで指定のデジカメ画像のExif情報(プロパティ)を取得する
on retExifAttributeData(aFile, aParam)
  
  
set aPOSIX to quoted form of POSIX path of aFile
  
  
set aRes to do shell script “sips –getProperty “ & aParam & ” “ & aPOSIX
  
set aList to paragraphs of aRes
  
set anItem to contents of last item of aList
  
  
set colonPos to (offset of “:” in anItem) + 2
  
set eRes to text colonPos thru -1 of anItem
  
  
return eRes
  
end retExifAttributeData

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2011/04/25 AppleScriptによる並列処理v3a

2011/04/22 AppleScriptによる並列処理 v3〜実行ムービー

AppleScriptを並列処理するAppleScriptの改良型、v3の実行中のムービーです。

先週末には出来上がっていたのですが、挙動がおかしい箇所があったので地道にデバッグしていました。

並列処理デモv3(5.7MB)

2011/04/16 AppleScriptによる並列処理 v2〜実際に使ってみての評価

AppleScriptによる並列処理 v2を実際に使ってみての評価です。

■前提となる話

たまたま、大量かつそこそこの容量のテキストファイルの処理をする必要があったので、マシンのCPU性能を生かすために並列処理を行わせてみた。

通常のデスクトップ用アプリケーションを複数同時起動できるわけではないし、複数のAppleScriptアプレットから同時に1つのアプリケーションにアクセスした場合にきちんと排他処理してくれたりするかどうかは不明(昔は、FileMaker Proがbegin transaction〜end transactionの構文をサポートしていたが、他で見かけたことがない)。そんなに高度なことを期待してもダメ。

InDesignとかIllustratorの処理を1台で並列実行とかいう話は無理。ただし、もしもMac OS X10.7になって複数ユーザーが同時ログインして別々のGUI環境を同時に実行できるとかいう環境になってくると、1つのユーザー環境から他のユーザー環境上のアプリケーションをコントロールできる可能性は……ないこともない。

AppleScriptのプログラムを動的に実行バイナリに変換して、同じ仕事を手分けして処理するという程度の話がこの話のゴール地点。テキストファイルの大量処理という話ならけっこう使える。

ひととおり使えるレベルのプログラムに育ったら、1台で複数の処理をやるのと同様に、複数のマシンで分散処理を行うプログラムを作ってみるとよさそう。安くてそこそこの性能のマシンを複数台集めるとか、オフィスや学校にあるMacを夜間に動かして仕事を分散処理させるのはけっこうよさそう。

■評価

処理対象のファイル一覧をスレッド数で分割して、まとめて渡すというやり方はよくない。処理対象のファイルにはサイズにバラツキがあるので、それぞれのスレッドの処理時間がバラバラ。「数」で割って仕事を割り振るのは、無駄が多いことが分かった。

p1.jpg

たとえば、4スレッドで並列処理を行っても、割り当て分を終わらせたスレッドは早々にプログラムを終了してしまう。処理が早く終わったスレッドは、処理が終わっていないスレッドの未処理分を処理すべきなのに、それができていない。最後のほうでCPUの利用効率が落ちてしまう。

また、途中でトラブルに遭遇して停止した場合、1スレッド文の処理がいきなりすべて無駄になってしまうのは時間の無駄すぎます。

そのため、1ファイルずつスレッド側に渡して処理するように変更すべきだと思われました。……というか、もう出来上がってテスト中です。

p2.jpg

2011/04/13 AppleScriptによる並列処理 v2

2010/09/19 openハンドラでファイルパス以外を渡す

読者の方からメールでお寄せいただいたプログラムの中に入っていて、「え? なにこれ?!」と驚いてしまったのが、このopenハンドラでファイルパス以外のものを渡すというやり方。

AppleScript Studioのアプリケーションに外部のAppleScriptから命令を渡すような場合に、コマンド入りのファイルを作成して、openハンドラ経由でそのファイルをAppleScript Studioアプリ側にオープンさせ、ファイルを経由してコントロール。

AppleScript Studioアプリケーションの内部ハンドラを外部からコントロールすることは事実上無理で、さまざまな迂回のための手段が考え出されてきましたが、ファイル経由でコマンド送信するのはなかなかいいやり方でした。……そう、処理スピードを考えなければ。

ファイルI/Oが毎回発生するので、スピードはいまひとつです。ただ、信頼性という意味では並列処理で連続して発生させても問題がなかったので、大丈夫だと考えています。

そのうえ、openハンドラをファイルI/Oを経由せずに呼び出せるのであれば、それに越したことはありません。

そんなところに飛び込んできた、openハンドラに渡せるのがファイルパスだけではないという情報。

さっそく、ためしてみました。

スクリプト名:openハンドラでファイルパス以外を渡す
set aRes to open {1, 2, 3}

on open {aFlag, bFlag, cFlag}
  display dialog aFlag as string
  
display dialog bFlag as string
  
display dialog cFlag as string
  
return true
end open

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

たしかに、openハンドラにファイルパス以外のものを渡しても大丈夫でした。ただ、openハンドラの受信パラメータに複数指定してしまうと、肝腎のファイルを(ドラッグ&ドロップで)渡したときにパラメータエラーになってしまいます。

drop1.jpg

そんなわけで、受信パラメータは1つに変更。その内容を判断して、処理するようにいろいろ試してみました。

スクリプト名:openハンドラでファイルパス以外を渡す 2
–recordをopenハンドラに渡すテスト
set aRec to {piyoID:10, piyoName:“piyopiyo”, piyoData:“ひよこさんだよ”}
set aRes to open aRec

–file aliasを単体でopenハンドラに渡すテスト
set aFile to choose file
set aRes to (open aFile)

–alias listをopenハンドラに渡すテスト
set aFol to choose folder
tell application “Finder”
  tell folder aFol
    set filesList to every file as alias list
  end tell
end tell
set aRes to open filesList

–レコード、リストに入ったaliasなどを受け付けるためのopenハンドラ
on open anObject
  set aClass to class of anObject as string
  
  
if aClass = “record” then
    set aID to piyoID of anObject
    
set aName to piyoName of anObject
    
set aData to piyoData of anObject
    
set aRes to ((aID as string) & return & aName & return & aData)
    
  else if aClass = “list” then
    –listが渡された場合
    
set bClass to (class of (first item of anObject)) as string
    
if bClass = “alias” then
      –alias listが渡されたものとして判定
      
set aRes to length of anObject –テストで長さを数えて返す。実際にはループでファイルを処理するような処理を行う
    end if
    
  else if aClass = “alias” then
    –エイリアス(ファイルパス)が単体で渡された場合。実際には、渡されたaliasのファイルをオープンしたりチェックしたりする
    
set aRes to anObject as string
    
  end if
  
  
return aRes
end open

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2010/04/27 AppleScriptによる並列処理テスト

AppleScriptで並列処理を行うサンプルです。メイン(GUI)側はAppleScript Studio(Xcode 3.1.4 on Mac OS X 10.5)、サブ側は通常のAppleScriptで記述しています。

子プログラムからメインプログラム(画面つきのプログラム)に向けて、ファイルシステム経由でイベントを6プロセス並列で送信。子プログラム側では1〜1000まで順次カウントアップし、すべての子プログラムがカウントアップを終了したら、その時間を表示するようになっています。

yyyeyoyycyayee2010-04-27-10458e.jpeg

→ テストプログラムをダウンロードする

使用方法は……アーカイブを展開したら、「docOpen1」アプリケーションを起動して、「START」ボタンを押すだけです。

newimage.jpg

結果は、手元のマシンでは……

  CoreDuo 2.0GHzのMacBook Pro:95〜100秒
  Core2Duo 2.4GHzのMacBook Pro:90〜95秒
  Core i7 2.66GHzのMacBook Pro:55〜60秒

といったところです(Mac OS X 10.6.3上で計測)。Core i7のMacBook Proでは6プロセス並行して走らせてもまだCPUに余力があり、HyperThreadingで仮想的に4コアのCPUとして振る舞えることが、こうしたタイプのプログラムの実行に有利に働いているようです。Core 2 Duo 2.4GHzの環境ではCPUの全能力を必要としていたAppleScriptのプログラムが、余裕で動いてしまう様にはほれぼれします>Core i7

yyyeyoyycyayee2010-04-27-10504e.jpeg
▲MacBook Pro Core i7 2.66GHzで本サンプルが稼働中の負荷

本サンプルの本当の目的は、並列処理時の子プログラムからメインプログラムへの状況・結果通知のテストでした。それぞれの子プログラムが並列でてんでバラバラにメッセージを投げた場合でも、イベントを取りこぼさずに正しく処理できることを確認できました。

パラメータをファイルに書き出して、そのファイルをメインプログラムでオープンさせるようにイベントを投げるというシンプルな処理ですが、並列処理時や長期間に渡る処理を行わせた場合の時間計測など、さまざまな用途が考えられます。実際に、ぜんぜん速度を要求されない「アドレスブック.app(のプラグインAppleScript)からAppleScript Studioアプリへのデータ転送」に、このファイルシステム経由のイベント送信を使って実装したことがあります。

本当は、こんなに短い間隔で連続的に子プログラム→メインプログラムの方向でイベントを送るようなシーンは考えていませんでした。かなりまとまった処理を子プログラムに行わせて、子プログラム側の処理終了後にその実行結果なりエラー内容なりを親プログラム側に伝えられればよい、というスタンスです。

さらに……本来であれば子プログラムの生成については、ダイナミックにその数を増減させられるのですが、GUIのプログラムに経過を表示する関係で、本サンプルでは6プロセス固定で行っています。

とても高価なため自分の手元にはないのですが、もっとCPUコア数の多いMacProなどで処理を行った場合の速度などが分かると有意義でしょう。速いマシンでの実行結果(秒数)については、コメント欄にて教えていただけると助かります。

2009/08/29 Snow LeopardのAppleScriptに関するリリースノート(2)

Snow LeopardのAppleScriptについてのリリースノートのうち、変更点に関するものが別途アップされていました(AppleScript Users MLより)。

Mac Dev Center: AppleScript Release Notes: 10.6 Changes

(more…)

2009/03/30 AppleScriptによる並列処理実験用アプレット

AppleScriptによる並列処理実験に用いたアプレットです。

とくに、手の込んだところはひとつもないのですが、このAppleScriptを保存する際に、「アプリケーションバンドル」形式で保存し、さらにオプションで「実行後、自動的に終了しない」チェックボックスをオンにしておく必要があります。

sub.zip

スクリプト名:sub
on run
  identifyMe()
end run

on identifyMe()
  activate
  
  
tell application System Events
    set pName to name of every process whose frontmost is true and visible of it is true
  end tell
  
set aName to contents of first item of pName
  
  
display dialog aName buttons {”OK“} giving up after 1
end identifyMe

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2009/03/30 アプレットをコピーしてリネーム v2

AppleScriptによる並列処理実験Scriptのv2です。v1では、複数のアプレットがDockに表示され……16プロセス起動すると同じアイコンが16個並んでしまいましたが、このv2ではInfo.plistのLSUIElementエントリを作成して、Dockに表示しないようにします。

あとは、アプレットを複製する場所を~/Library/Caches/TemporaryItemsあたりにでもして、終了後の実行ファイルの削除あたりを行うようにライブラリを整理すればいい感じでしょうか。

スクリプト名:アプレットをコピーしてリネーム v2
property maxNum : 10

set aFile to choose file
選択したファイルがバンドル形式のアプレットかどうかをチェック
set apRes to chkAppBundle(aFile) of me
if apRes = false then return

set aFile to aFile as alias

repeat with i from 1 to maxNum
  set aName to (”sub & i as string) & .app
  
  
ファイルをコピーしてリネーム
  
tell application Finder
    set dRes to (duplicate aFile)
    
set dRes to dRes as alias
    
set name of dRes to aName
  end tell
  
  
各アプレットのCFBundleNameを書き換えてLaunch
  
set newApp to renameAppBundle(dRes, aName) of me
  
tell application Finder
    open newApp
  end tell
end repeat

指定アプレットのInfo.plistを書き換える
on renameAppBundle(aFile, aName)
  アプリケーションバンドル内のInfo.plistへのフルパスを組み立てる
  
set aFile to aFile as alias
  
  
set aPosixFile to POSIX path of aFile
  
set pListpath to aPosixFile & Contents/Info.plist
  
  
CFBundleNameを書き換える
  
tell application System Events
    set plistRec to (value of property list file pListpath)
    
set |CFBundleName| of plistRec to aName
    
set plistRec to plistRec & {|LSUIElement|:1} Dockに表示させない
    
set value of property list file pListpath to plistRec
  end tell
  
  
return aFile
end renameAppBundle

指定ファイルがバンドル形式のアプレットかどうかチェック
on chkAppBundle(a)
  set aInfo to info for a
  
set fType to file type of aInfo “APPL”
  
set fCreator to file creator of aInfo “aplt”
  
set typeIdentifier to type identifier of aInfo “com.apple.application-bundle”
  
  
log {fType, fCreator, typeIdentifier}
  
  
if {fType, fCreator, typeIdentifier} = {”APPL“, aplt“, com.apple.application-bundle“} then
    return true
  else
    return false
  end if
end chkAppBundle

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2009/03/30 アプレットをコピーしてリネーム v1

AppleScriptによる並列処理の実験Scriptです。あらかじめ、他にバンドル形式のアプレットをAppleScriptで作成しておき……そのアプレットをコピーしつつバンドル内のInfo.plistの中のエントリを書き換えて別名のアプレットに仕立て上げ、別々のプロセスとして扱えるようにします。

最近のMacは最低でもデュアルコア、最高で16コアというマルチコア化まっしぐらの状況なので、時間のかかる処理については並列処理を考えたほうが得策です。AppleScript自体に並列処理のための機能は……複数のアプレット間でプロセス間通信を行ったりプロパティを参照し合ったりというぐらい。いまひとつマルチコア時代に適した便利な機能を持っていませんが、なければ作るまでのこと。

そこで、アプレットのファイルをコピーして必要なプロセス分用意し、さらにそのバンドル内のInfo.plistを書き換えて、別プロセスとして扱えるように細工します。

これで、プロセス名(アプリケーション名)を個別に指定してハンドラを呼び出したり、プロパティの参照/書き換えを行ったりできるので、1つの時間のかかる処理(大量のJPEG画像ファイルの破損チェックなど)を複数プロセスの生成・起動により時間短縮できるものと思われます。

複数のアプレットから特定のアプリケーション(QuickTime Playerなど)に同時アクセスするのは得策ではないため、それらのリクエストを受け付けるキューイング用のアプレットを別途用意するなどの対策は必要になってくることでしょう。

私の手元にはDual Coreのマシンしかないので、どこからか実験用に16コアのMac Proでも貸していただければ、さまざまな検証も行えるのですが(^ー^;。

スクリプト名:アプレットをコピーしてリネーム v1
property maxNum : 10

set aFile to choose file
選択したファイルがバンドル形式のアプレットかどうかをチェック
set apRes to chkAppBundle(aFile) of me
if apRes = false then return

set aFile to aFile as alias

repeat with i from 1 to maxNum
  set aName to (”sub & i as string) & .app
  
  
ファイルをコピーしてリネーム
  
tell application Finder
    set dRes to (duplicate aFile)
    
set dRes to dRes as alias
    
set name of dRes to aName
  end tell
  
  
各アプレットのCFBundleNameを書き換えてLaunch
  
set newApp to renameAppBundle(dRes, aName) of me
  
tell application Finder
    open newApp
  end tell
end repeat

(*
delay 1

repeat with i from 1 to maxNum
  set aName to (”sub” & i as string) & “.app”
  tell application aName
    identifyMe()
  end tell
  delay 1
end repeat
*)

指定アプレットのInfo.plistを書き換える
on renameAppBundle(aFile, aName)
  アプリケーションバンドル内のInfo.plistへのフルパスを組み立てる
  
set aFile to aFile as alias
  
  
set aPosixFile to POSIX path of aFile
  
set pListpath to aPosixFile & Contents/Info.plist
  
  
CFBundleNameを書き換える
  
tell application System Events
    set plistRec to (value of property list file pListpath)
    
set |CFBundleName| of plistRec to aName
    
set value of property list file pListpath to plistRec
  end tell
  
  
return aFile
end renameAppBundle

指定ファイルがバンドル形式のアプレットかどうかチェック
on chkAppBundle(a)
  set aInfo to info for a
  
set fType to file type of aInfo “APPL”
  
set fCreator to file creator of aInfo “aplt”
  
set typeIdentifier to type identifier of aInfo “com.apple.application-bundle”
  
  
log {fType, fCreator, typeIdentifier}
  
  
if {fType, fCreator, typeIdentifier} = {”APPL“, aplt“, com.apple.application-bundle“} then
    return true
  else
    return false
  end if
end chkAppBundle

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に