本日配布開始になったmacOS 26.3 Beta(25D5087f)において、これまで確認されていた「Finderのempty trashバグ」が出なくなったことを確認しました。
これは、AppleScriptからFinderのゴミ箱のクリア(empty trash)コマンドを実行すると、コマンドの実行後にエラーを返すというmacOS 26のリリース時から発生していたバグです。
ただし、macOS 26.3は1月後半のリリースが見込まれているため、それまでにバグが復活する可能性もあります。
本日配布開始になったmacOS 26.3 Beta(25D5087f)において、これまで確認されていた「Finderのempty trashバグ」が出なくなったことを確認しました。
これは、AppleScriptからFinderのゴミ箱のクリア(empty trash)コマンドを実行すると、コマンドの実行後にエラーを返すというmacOS 26のリリース時から発生していたバグです。
ただし、macOS 26.3は1月後半のリリースが見込まれているため、それまでにバグが復活する可能性もあります。
Finderを終了させたままにしておくAppleScriptです。
この種類のQ&Aだと、
do shell script "killall Finder"
といった回答が書かれがちですが、これだと終了させたままにはできません。
Finderを終了させたままにしておく方法について調べてみたら、見つかったのでまとめておきました。
| AppleScript名:Finderを終了させる.scpt |
| do shell script "defaults write com.apple.Finder QuitMenuItem -boolean true" tell application "Finder" to quit |
新刊電子書籍「AppleScript基礎テクニック(33)複数のアプリをコントロール」を刊行しました。全74ページ、サンプルAppleScriptアーカイブつき。
→ 販売ページ
macOS上のGUIアプリの書類やウィンドウ中で選択中のオブジェクトを取得し、その情報をもとにAppleScriptで処理を行なって、もとの選択オブジェクトに反映させるといった処理を、日常的に行っています。
このような書き方ができると、まるでAppleScriptによってGUIアプリの機能を拡張しているようにも見えます。実際には外部で処理を行なっていたとしても、使い勝手としては拡張しているように振る舞えます。
ある意味、AppleScriptの備える最強の機能といってもよいでしょう。本書で、この強力なselection機能について、その概要から実例、注意点にいたるまで幅広くご紹介いたします。
PDF 74ページ、Zipアーカイブ添付
■最初に:macOS 13以降では最初にステージマネージャを必ずオフにしてください
macOS 13.x
macOS 14.x
macOS 15.x
その他、オフにすることが望ましい機能
■アプリ上の選択中のオブジェクトにアクセスする予約語「selection」
GUIアプリ上の選択中のオブジェクトを知る
選択中のオブジェクトは、1つだけじゃない
選択中のオブジェクトを加工することも
選択中のオブジェクトの情報分析
■選択中のオブジェクトの情報をもとに他のアプリで処理
selection系の機能をサポートしているアプリ一覧
selectを含む予約語を持つアプリと予約語①
selectを含む予約語を持つアプリと予約語②
selectを含む予約語を持つアプリと予約語③
■selectionの主な実例
selectionの取得方法①(Finder)
selectionの取得方法②(Finder)
selectionの書き換え①(Finder)
selectionの書き換え②(Finder)
selectionの取得方法③(Finder)
selectionの取得方法(住所録)
selectionの書き換え(住所録)
selectionの書き換え(住所録)
selectionの取得方法①(Keynote)
selectionの取得方法②(Keynote)
selectionの書き換え(Keynote)
selectionの取得方法①(ミュージック)
selectionの取得方法②(ミュージック)
selectionの書き換え(ミュージック)
selectionの取得方法①(CotEditor)
selectionの取得方法②(CotEditor)
selectionの書き換え(CotEditor)
selectionの取得方法①(Numbers)
selectionの取得方法②(Numbers)
active sheetの取得方法(Numbers)
selection rangeの取得方法①(Numbers)
selection rangeの取得方法②(Numbers)
selection rangeのセル内容書き換え①(Numbers)
selection rangeのセル内容書き換え②(Numbers)
selection rangeのセル内容書き換え③(Numbers)
selectionの取得方法①(Excel)
selectionの取得方法②(Excel)
選択中のワークシートの取得方法(Excel)
selectionの書き換え(Excel)
selectionの取得方法(Pixelmator Pro)
select-を含む予約語解説①(Pixelmator Pro)
select-を含む予約語解説②(Pixelmator Pro)
select-を含むコマンド実例①(Pixelmator Pro)
select-を含むコマンド実例②(Pixelmator Pro)
select-を含むコマンド実例③(Pixelmator Pro)
select-を含むコマンド実例④(Pixelmator Pro)
select-を含むコマンド実例⑤(Pixelmator Pro)
select-を含むコマンド実例⑥(Pixelmator Pro)
select-を含むコマンド実例⑦(Pixelmator Pro)
select-を含むコマンド実例⑧(Pixelmator Pro)
select-を含むコマンド実例⑨(Pixelmator Pro)
select-を含むコマンド実例⑩(Pixelmator Pro)
select-を含むコマンド実例⑪(Pixelmator Pro)
■selectionを使用うえで注意すべき点
注意点1:大量のオブジェクトの受け渡しに要注意
注意点2:情報の書き戻し時には時間がかかる例も
注意点3:選択オブジェクトの種別判定を①
注意点3:選択オブジェクトの種別判定を②
Betaのときには起こっていなかった現象で、macOS 15.1で確認されています。
スクリプトエディタでFinderのAppleScript用語辞書を閲覧できません。
Finderは/System/Library/CoreServicesフォルダに入っており、このフォルダへのアクセスが「より厳しく」なったのでしょう。
ただ、実際にFinderがAppleScript対応しなくなったわけでもなければ、FinderのSDEFが除去されたわけでもありません。
実際にFinderの(パッケージ内容をコンテクストメニューから表示させたうえで)SDEFをコピーして、コピーしたものをスクリプトエディタで閲覧するとよいでしょう。
Appleは何の発表もなく、重要な情報を変更することがあります。とくに、日本語ローカライズされた内容だと英語圏のユーザーの関心は薄いですし、Appleのエンジニアが「理解できない」ケースも見られます。日本語の単語分解(≒形態素解析)について、macOS 10.5あたりまで「文字種類が変わったら単語の切れ目」とかいう無茶苦茶なロジックで処理されていましたが、それを「そういうのじゃない」とことあるごとにレポートしてきましたが、理解されてきませんでした。
Finderが管理しているファイルの種別(kind属性)は、ローカライズされたものが返ってくることで知られていましたが、macOS 14でそれが変更されたことがわかりました(最近MacBook Air M2を追加して、macOS 14環境を真剣に使い始めたので)。
こんな重要な変更は、気軽に行なってほしくないですし、変更したことを通達してほしいのですが(ーー;
以前からFinderのkindの内容については「ローカライズしてほしくないなぁ」と感じていましたが、このあたりのファイル種別については、UTI(com.image.pngなど)を利用するほうが、利用者の言語環境の変化を意識しなくていいですし、こうした些細なローカライズの変更の影響を受けなくてよいでしょう。
ただ、このあたりのやり方がいつも乱暴です>Apple
Release Notesもまともに書かなくなりましたし、どういうつもりなんだか。
Appleへの指摘事項として、Shortcutsで画像を扱うアクションが「写真」だったり「イメージ」だったり「画像」だったりと、用語のゆらぎが激しいという話があります。この点はAutomatorの登場時を彷彿とさせるものがあります。「これで使えというのには無理がある」「類似語の表記ゆらぎを吸収する仕組みが必要なのでは?」という指摘を行なっているのですが、そういう方向の努力として「種別」(Kind)のローカライズに手を入れた……と、考えられなくはありません。
それにしても、やっていることがお粗末すぎます。
| AppleScript名:kind checker |
| tell application "Finder" set aSel to selection set anItem to first item of aSel properties of anItem end tell |
Finder上で選択中のAppleScriptバンドル形式書類をスクリプトエディタでオープンして、scpt形式で保存し直すAppleScriptです。
スクリプトエディタのコンテクストメニューが.scpt形式しか認識しないので、バンドル形式のScriptを変換するために作ったものです。
Finderの選択中のファイルをフィルタするのに、フィルタ参照ではなくUTIを求めて判定しています。
「AppleScript最新リファレンスv2.8対応」の付録Scriptの加工用に作ったものです。バンドル形式への変換は書いてあったものの、scpt形式に変換するものは書いていなかったので急遽、用意しました。
| AppleScript名:Finder上で選択中のASバンドル書類をオープンしてscpt形式で再保存.scptd |
| — – Created by: Takaaki Naganoya – Created on: 2023/10/20 — – Copyright © 2023 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" use scripting additions use framework "Foundation" property |NSURL| : a reference to current application’s |NSURL| property NSArray : a reference to current application’s NSArray property NSPredicate : a reference to current application’s NSPredicate property NSURLTypeIdentifierKey : a reference to current application’s NSURLTypeIdentifierKey on run set aResList to main("com.apple.applescript.script-bundle") of me set ngList to {} repeat with i in aResList set anAlias to contents of i set aRes to saveAppleScriptAsScript(anAlias) of me if aRes = false then set the end of ngList to contents of i end if end repeat return ngList end run –scptdファイルをaliasで渡すと、scptファイルで同じ場所に保存し直す on saveAppleScriptAsScript(aFile) set dPOSIX to POSIX path of aFile if dPOSIX ends with "/" then set dPOSIX to (strings 1 thru -2 of dPOSIX) end if –フルパスから、拡張子を付け替える set newPath to changeExtFromPath(dPOSIX, "scpt") of me set newFile to POSIX file newPath tell application id "com.apple.scripteditor2" try open aFile tell front document check syntax end tell save front document as "script" in file newFile close front document without saving return true on error return false end try end tell end saveAppleScriptAsScript –POSIX pathの拡張子を付け替える on changeExtFromPath(aPath, newExt) set pathString to current application’s NSString’s stringWithString:aPath set newPath to ((pathString’s stringByDeletingPathExtension())’s stringByAppendingPathExtension:newExt) as string return newPath end changeExtFromPath on main(acceptUTI) tell application "Finder" set aSel to selection as alias list end tell set aList to {} repeat with i in aSel set anAlias to contents of i set aUTI to getUTIfromPath(anAlias) of me if aUTI is not equal to missing value then set uRes to filterUTIList({aUTI}, acceptUTI) of me if uRes is not equal to {} then set the end of aList to contents of i end if end if end repeat return aList end main –AliasからUTIを求める on getUTIfromPath(anAlias) set aPOSIXpath to POSIX path of anAlias set aURL to current application’s |NSURL|’s fileURLWithPath:aPOSIXpath if aURL = missing value then return missing value set aRes to aURL’s resourceValuesForKeys:{current application’s NSURLTypeIdentifierKey} |error|:(missing value) if aRes = missing value then return missing value return (aRes’s NSURLTypeIdentifierKey) as string end getUTIfromPath –UTIリストが指定UTIに含まれているかどうか演算を行う on filterUTIList(aUTIList, aUTIstr) set anArray to NSArray’s arrayWithArray:aUTIList set aPred to NSPredicate’s predicateWithFormat_("SELF UTI-CONFORMS-TO %@", aUTIstr) set bRes to (anArray’s filteredArrayUsingPredicate:aPred) as list return bRes end filterUTIList |
Twitter上で@usagimaruma氏がレポートしたところにより、FinderにSiri用の隠しAppleScriptコマンド「openVirtualLocation」が存在していることが明らかになりました。
ドキュメントに載っていないFinder AppleScriptの命令を見つけた。tell構文でFinderに対して 'openVirturalLocation "AirDrop"' みたいにすると、AirDropやiCloud Driveのウインドウを直接開ける。 pic.twitter.com/SZHb8c14T7
— usagimaru ⌘ (@usagimaruma) November 19, 2022
tell application "Finder" openVirtualLocation "AirDrop" end tell
/System/Library/CoreServices/Finder.app/Contens/Applications の下にある、
といった小型アプリケーションが、上記のコマンドを利用して機能を呼び出しています。バイナリをダンプすると、”openVirtualLocation”コマンドの部分を生AppleEventsで記述してあり、少し不思議な雰囲気です。
早速、手元の環境でチェックしてみたところ、報告されたとおりに動きます。
hidden=”yes”に設定されているために、普通にFinderをsdefをスクリプトエディタで確認しただけでは表示されません。
過去にさかのぼって、どのバージョンのOSから使えるのかを確認してみたところ、
macOS 10.14:NG
macOS 10.15:NG
macOS 11.6:Exist
macOS 12.6:Exist
macOS 13.x:Exist
と、Siriの搭載とリンクしているというよりは、ショートカット.appの搭載とリンクしているように見えるので、macOS 11のFinderにこのコマンドは搭載されていないのではないか、と推測します。
macOS 12.xはAppleScriptの処理系に対して、主にセキュリティ面でいろいろ修正が加わっています。
この修正は、セキュリテイを「高める」という名目のもとに行われているのですが、セキュリティ面での課題さえ片付けられれば、その他に悪影響を及ぼしていたとしても「知ったことではない」というのがAppleの態度です。そして、その問題に対してユーザー側から文句が出てこなければ、そのままです。
とくに、深謀遠慮な考えとか、素晴らしい見通しとかはなく、「上から言われたからやっている」というやっつけ仕事感を感じます。
AppleはSteve Jobsが作り上げた秘密警察みたいな組織になっていて、チーム間の権限の切り分けが病的なまでに行われており、チームが違うと会社が違うぐらいの隔たりが発生しています。それは、Steve Jobsという「垣根を無視して横断して歩く異物」がいたから成立する組織であって、官僚化、硬直化が絶賛進行中といったところです。
話を戻しますが….たしかに、そうした機能的なアップを伴わない修正で何も問題(副作用)が起こらなければ「セキュリティが高まったのでよかったね」という美談になるわけですが、たいていの場合にはそうなりません。意図していなかった箇所に副作用が生じます。
あるいは、セキュリティのポリシー同士が実は矛盾を生んでいる、という状況になっていて、Aという問題とBという問題を解決した結果、あらたにCというもっと巨大な問題が発生する、とかいった状況は容易にあり得るわけです。それでも、各担当者は誠意をもってその仕事に取り組んでいるわけで、こうした「人間的に尊敬できて素晴らしい能力を持ったスタッフ」による「熱心かつ誠意あふれる真摯な仕事」が合成された結果、「見たことも聞いたこともない間抜けな理由から生じる猛毒にまみれた悪意」が合成されてしまうことが、現在のTim CookのAppleの下ではあり得るのです。
「Finder上で選択中のファイルをそのままオープンする」
というのは、ここ数年というよりもAppleScriptを覚えたてのころにちょろっと書いて実行したぐらいであり、実際のところ「それがどうした?」というレベルの処理です。
| AppleScript名:Finder上で選択中のファイルをオープン.scpt |
| –macOS 12.3でエラーになる処理 tell application "Finder" open selection end tell |
Finder上で選択したファイルに対する処理は、きょうび何かのアプリケーションに渡さなくてもAppleScriptだけで処理できてしまうことが多いということもありますし(画像とか)、選択されたファイルをそのままオープンするという「1=1」みたいな処理はやりません。
選択したフォルダの中をすべてSpotlight経由で走査して、指定の形式のファイルだけをリストアップして、順次処理するようなものになっています。
ただ、10年たっても20年たっても「1=1」みたいな処理しかしていない人がけっこういて驚かされると同時に、意外なところで(Adobeのアプリケーションでアプリケーション間の連携に)使っていたりして、修正されないと困るケースは多いようです。
Shane StanleyがLateNight Softwareのフォーラムに投稿した、こうした処理への迂回Scriptがありました。さすがです。
Finder経由で書類のオープンと、その書類を作成したアプリケーションの起動を促すという、macOS 12.3で問題が起こっている処理を、Cocoaの機能を用いることで迂回してしまおうというものです。
ただ、そのままではFinder上で指定したファイルを1つオープンするという実証コードのレベルのものだったので、複数のファイルが選択されたものをオープンするように書き足してみました。
| AppleScript名:macOS 12.3でFinder上の選択中のファイルをオープン.scpt |
| — – Created by: Shane Stanley – Created on: 2022/03/24 – Modified by: Takaaki Naganoya – Modified on: 2022/03/27 — — macOS 12.3でFinder上のselectionをただopenすると、作成したアプリケーションは起動するが、書類はオープンされないバグ – に対処したもの。複数ファイルの選択状態を処理する場合がほとんどなので、若干追記 – ただ、漫然と選択したファイルをオープンするという処理はやっていないので(なにがしかの処理を自前でやるので) use framework "AppKit" use framework "Foundation" use scripting additions tell application "Finder" set aSel to selection as alias list if aSel = {} then return end tell openFiles(aSel) of me on openFiles(pathList as list) repeat with i in pathList set j to contents of i openFile(POSIX path of j) of me end repeat end openFiles on openFile(thePath as string) — POSIX path set ws to current application’s NSWorkspace’s sharedWorkspace() set theURL to current application’s |NSURL|’s fileURLWithPath:thePath ws’s openURL:theURL end openFile |
電子書籍を作るのにPagesやKeynoteを使っており、「AppleScriptによるWebブラウザ自動操縦ガイド」(以下、Webブラウザガイド)も全ページPagesで作っています。
PagesやKeynoteでは書籍作成用としては機能が素朴すぎて、足りない点はAppleScriptでツールを作って、作業の手間を減らしています。それらの補助Scriptは、各種パラメータをその本に合わせて固定して使用しています。
Webブラウザガイドは全14章で構成されているため、ページの左右につけている「ツメ」(Index)は1から14までの数字が入っています。
今後もツメチェックAppleScript(座標、塗りつぶし色と非選択色の自動判別、ファイル名からの該当章の自動ピックアップ)を他の書籍用にも運用していくつもりですが、この「全14章」という仕様は固定なので、章構成が異なる他の本のプロジェクトでは、自動で章の数をかぞえてくれるとよさそうだと考えました。
だいたい電子書籍のファイルについては、フォルダ分けして2階層ぐらいで管理しているので、その階層数については決め打ちでDoc rootフォルダを計算(parent of parent of….)するようにしました。そして、全フォルダのフォルダ名称を取得。
ダイアログで最終章を選択させると、そこから章番号を自動抽出して(「XX章」と書かれていることが前提)、その番号を返します。
こういう用途を考えると、階層構造をそのまま選択できるNSOutlineViewを選択用の部品に使えると便利で……これまでにもedama2さんと意見交換しつつNSOutlineViewをNSAlertダイアログ上に表示するといった試作も何回か検討してきたのですが、スクリプトエディタ/Script Debugger上で記述するAppleScriptObjCではこの部品を扱うのがとても難しいんですね。
ならば、Xcode上で記述するAppleScriptObjCにAppleScript用語辞書を持たせて、階層ファイル構造を選択させる専用の補助アプリケーションを作ってもいいのかも? ただ、Xcode 13.x系が壊れて使えないままの環境であるため、いまXcodeでビルドするわけにもいかないのでした。
choose fileコマンドやchoose folderコマンドに「icon view」「list view」「column view」といった初期表示状態を指定できる機能があれば、それで済むような気もしますが、どうせAppleに要望出してもこういうのは通らないので、自分で作ったほうが確実で早いですわー。
にしても、この通常ウィンドウと見分けがつかないファイル選択ダイアログ、macOS 11で最初に見たときには「正気か?!」と、腰を抜かしました。あいかわらず、この決定を下した責任者は●●だと思いますが、せめてもう少し視覚的に見分けがつくようにできなかったもんでしょうか。
| AppleScript名:書籍フォルダの階層をさかのぼって、ツメに掲載する最大チャプターを推測 v2.scptd |
| — – Created by: Takaaki Naganoya – Created on: 2022/02/26 — – Copyright © 2022 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use scripting additions tell application "Pages" tell front document set filePath to (file of it) as alias end tell end tell tell application "Finder" set parentFol to (parent of parent of filePath) tell parentFol set fNames to name of every folder end tell end tell set folName to contents of (choose from list fNames with prompt "書籍のツメに載せる最終章のフォルダを選択") set cNum to retChapter(folName as string) of me –> 14 –ファイル名から「章」情報を抽出 on retChapter(aStr) set wList to words of aStr set aCount to 1 repeat with ii in wList set jj to contents of ii if jj = "章" then return contents of item (aCount – 1) of wList end if set aCount to aCount + 1 end repeat return 0 –Illeagal file name end retChapter |
日常的に生じている不満を解消するための、ちょっとしたかき捨てScript……になるはずだったものです。
Classic Mac OSからMac OS Xへの移行後、Finderの仕様で大きく変わった点が1つあります。「同じフォルダのウィンドウを複数枚オープンできるようになった」点です。
その結果、
といったように、同じフォルダを指し示すウィンドウが何枚もたまる現象が起きています。これは別にバグでも不具合でもありません。仕様です。
この重複Windowを掃除するためのScriptを書いてみました。
| AppleScript名:ターゲットが同じWindowを取得(未遂).scpt |
| tell application "Finder" tell window 1 set aTarg to target end tell set wList to every window whose target is equal to aTarg end tell |
何も考えずに書き始めると、こんな(↑)感じでしょう。ただ、このScriptは動きません。フィルター参照は、たとえばファイル名や拡張子、ファイル種別(kind)あたりには使えるものの、この「target」属性に対しては効きません。
そこで、仕方なくちょっと腰をすえて書いてみました。これ(↓)を動かすと、
のように重複ウィンドウが一掃されます。これでいいはずです。
| AppleScript名:targetが重複しているFinder Windowをクローズする.scpt |
| — – Created by: Takaaki Naganoya – Created on: 2021/07/22 — – Copyright © 2021 Piyomaru Software, All Rights Reserved — set clList to {} tell application "Finder" set wList to every window –> {Finder window id 1775 of application "Finder", Finder window id 1612 of application "Finder", Finder window id 1740 of application "Finder", Finder window id 1641 of application "Finder", Finder window id 1630 of application "Finder", Finder window id 1618 of application "Finder", Finder window id 1599 of application "Finder", Finder window id 1592 of application "Finder", Finder window id 1586 of application "Finder", Finder window id 1580 of application "Finder", Finder window id 1575 of application "Finder", Finder window id 1569 of application "Finder", Finder window id 1563 of application "Finder"} set tList to (target of every window) as alias list –> {alias "Macintosh HD:Users:me:Public:ドロップボックス:", alias "Macintosh HD:Users:me:Documents:AppleScript 12.0:", alias "Macintosh HD:Users:me:Public:ドロップボックス:", alias "Macintosh HD:Users:me:Public:ドロップボックス:", alias "Macintosh HD:Users:me:Public:ドロップボックス:", alias "Macintosh HD:Users:me:Public:ドロップボックス:", alias "Macintosh HD:Users:me:Public:ドロップボックス:", alias "Macintosh HD:Users:me:Public:ドロップボックス:", alias "Macintosh HD:Users:me:Public:ドロップボックス:", alias "Macintosh HD:Users:me:Public:ドロップボックス:", alias "Macintosh HD:Users:me:Public:ドロップボックス:", alias "Macintosh HD:Users:me:Public:ドロップボックス:", alias "Macintosh HD:Users:me:Public:ドロップボックス:"} –ターゲットフォルダをユニーク化 set bList to removeDuplicates(tList) of me –> {alias "Macintosh HD:Users:me:Documents:AppleScript 12.0:", alias "Macintosh HD:Users:me:Public:ドロップボックス:"} –ユニーク化したターゲットでループ repeat with i in bList set j to (contents of i) as alias set firstF to true –ウィンドウでループ repeat with ii in wList set jj to contents of ii set tmpTarg to (target of jj) as alias if tmpTarg is equal to j then –最初の1つ目のWindowだけ残す if firstF = true then set firstF to false else –2個目以降のWindowはクローズ対象リストに入れる set the end of clList to jj end if end if end repeat end repeat –クローズ対象とされるFinder Windowを順次クローズ repeat with i in clList set j to contents of i try ignoring application responses close j end ignoring end try end repeat end tell on removeDuplicates(aList) set newList to {} repeat with i from 1 to (length of aList) set anItem to item 1 of aList set aList to rest of aList if {anItem} is not in aList then set end of newList to anItem end repeat return newList end removeDuplicates |
edama2さんがコメント欄に投稿してくださったプログラムを掲載しておきます。自分が「安全のためにこのぐらいの処理は必要(かも?)」と付けまくった処理を「それ別に実際のところ必要ないんじゃない?」と省略された感じです。
あとは、edama2さんのScriptだと「最前面のWindowのtargetと同じtargetを持つWindowをクローズする」という動作ですが、自分のScriptは「targetが重複しているWindowは1つを残してあとすべてをクローズする」という動作を行うので、厳密にいえば違うものです。
| AppleScript名:targetが重複しているFinder Windowをクローズする v2.scpt |
| – Created by: edama2 – Created on: 2021/07/22 tell application "Finder" tell front window set aTarg to target end tell set aList to (every Finder window) as list repeat with num from 2 to count aList set anItem to (aList)’s item num if (anItem’s target is aTarg) then close anItem end repeat end tell |
Safariの最前面のウィンドウで再生中のYouTubeムービーの情報を取得し、LAN上の別のMacで再生を引き継ぐ(ハンズオーバーする)AppleScriptです。
macOS 10.13以降、リモートAppleEvents経由でGUIアプリケーションを直接操作する機能が復活しました(Mac OS X 10.7〜10.12ぐらいまでAppleScriptアプレット間のみリモート通信が許可されていた状態)。
メインマシンで再生中のYouTubeムービーを、LAN上の他のマシンに引き継がせてみました。再生を引き継がれる方のマシンでは、システム環境設定の「共有」で「リモートApple Events」の項目をオンにしています(自分のマシンではすべてこの項目をオンにしています)。
AppleScript書類のコメント(Finderコメント)にパスワードを書いておくと、それを読み取って使用するようにしてみました。
リモートマシン上のアプリケーションの操作は、ただリモートマシン上のアプリケーションを指定すればOKなのですが、操作対象のアプリケーションが起動していない場合にはエラーになります。これは、とても困る仕様です。
そこで、リモートマシンのFinder経由でアプリケーションファイルをオープンすることで、リモートマシン上でSafariを起動します。オープン対象をapplication file “Safari”と指定するとエラーになりますが、application file id “com.apple.Safari”と指定するとエラーになりません。
以前調査しておいた内容をそのまま使っています。再生中ならPauseし、再生中の位置(時間)情報を取得し、文字列で指定するために加工してYouTubeのURLに追加しています。URLの加工部分は少々手抜きをしています。
とくに問題なく、メインマシンから他のマシン(macOS 10.15.7/macOS 11.0beta9)にLAN経由で再生をハンズオーバーできました。
実際に、コントロール先のマシン名(Bonjour名)をremoteMachineNameに、ユーザー名をremoteUserNameに、パスワードを実行するAppleScript書類のFinderコメントに書き込んで実行してください。スクリプトエディタ上でもスクリプトメニューからでも問題なく実行できています。
あとは、Safari上のYouTube再生をフルスクリーンで行えるとよいのですが、少し試した範囲ではできなかったので、また地道に調べておく感じでしょうか。
| AppleScript名:LAN上の別のMacでYouTubeムービー再生をハンズオーバー v2.scpt |
| — – Created by: Takaaki Naganoya – Created on: 2020/10/08 — – Copyright © 2020 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use scripting additions property |NSURL| : a reference to current application’s |NSURL| property NSMetadataItem : a reference to current application’s NSMetadataItem set remoteMachineName to "MacMini2014.local" set remoteUserName to "maro" –ScriptのCommentに書いておいたパスワードを拾って使う set mePath to (path to me) –FinderからCommentは拾えるが、メタデータ経由で取得する処理も試してみた set remoteUserPass to getFinderComment(POSIX path of mePath) of me tell application "Safari" if running then tell front document set aURL to URL –最前面のウィンドウがYouTubeの場合のみ処理 if aURL does not start with "https://www.youtube.com/" then display notification "エラー: YouTubeを再生していないため、ハンズオーバーしませんでした" return end if –再生中のポジションを取得 set tRes to (do JavaScript "document.querySelector(’#movie_player video’).currentTime;") –再生状況を取得 set pRes to (do JavaScript "document.querySelector(’#movie_player video’).paused;") if pRes = false then –再生中であればPauseする set aRes to (do JavaScript "document.querySelector(’#movie_player .ytp-play-button’).click();") end if openYouTubeOnRemoteMachine(remoteUserName, remoteUserPass, remoteMachineName, tRes, aURL) of me end tell end if end tell –指定のリモートマシン上のSafariでYouTubeの指定ムービーの指定箇所からの再生を行う on openYouTubeOnRemoteMachine(remoteUser, remotePass, remoteMachineLocal, newDuration, newURL) set remoteMachineName to "eppc://" & remoteUser & ":" & remotePass & "@" & remoteMachineLocal –URLの加工。ちょっと手抜きをした if newDuration is not 0 then set tText to retTimeText(newDuration) of me if newURL contains "&" then set sepChar to "?" else set sepChar to "&" end if set newURL to newURL & sepChar & "t=" & tText end if using terms from application "Safari" tell application "Safari" of machine remoteMachineName if not running then –起動していなかったらあらためてSafariを起動 launchRemoteSafari(remoteMachineName) of me end if try close every document end try set aWin to make new document tell aWin set URL to newURL –フルスクリーン再生をためしてみたが、こういう書き方ではなかった模様(URLオープンを待つ必要もある) –set aRes to (do JavaScript "document.querySelector(’#movie_player playFullscreen’).click();") end tell end tell end using terms from end openYouTubeOnRemoteMachine –リモートマシン上でSafariを起動する on launchRemoteSafari(aMachine) using terms from application "Finder" tell application "Finder" of machine aMachine open application file id "com.apple.Safari" end tell end using terms from end launchRemoteSafari –数値を「h」「m」「s」でフォーマットして返す on retTimeText(aTime) set aHour to aTime div 3600 set aMinute to (aTime – (aHour * 3600)) div 60 set aSeconds to (aTime mod 60) set aString to "" if aHour > 0 then set aString to aHour & "h" end if if aMinute > 0 then set aString to aString & (aMinute as integer) & "m" end if if aSeconds > 0 then set aString to aString & (aSeconds as integer as string) & "s" end if return (aString as string) end retTimeText –Finderコメントをメタデータ経由で取得 on getFinderComment(aPOSIX) set aURL to |NSURL|’s fileURLWithPath:aPOSIX set aMetaInfo to NSMetadataItem’s alloc()’s initWithURL:aURL set metaDict to (aMetaInfo’s valuesForAttributes:{"kMDItemFinderComment"}) as record if metaDict = {} then return "" set aComment to kMDItemFinderComment of (metaDict) return aComment end getFinderComment |
Finder上で選択中のアプリケーションのplistファイルを探してFinder上で選択表示するAppleScriptです。
| AppleScript名:display selected application’s plist on Finder.scpt |
| — – Created by: Takaaki Naganoya – Created on: 2020/08/17 — – Copyright © 2020 Piyomaru Software, All Rights Reserved — use AppleScript version "2.5" –macOS 10.11 or later use scripting additions use framework "Foundation" use framework "AppKit" property |NSURL| : a reference to current application’s |NSURL| property NSArray : a reference to current application’s NSArray property NSPredicate : a reference to current application’s NSPredicate property NSURLTypeIdentifierKey : a reference to current application’s NSURLTypeIdentifierKey tell application "Finder" set aliasList to selection as alias list end tell –Filter selection application bundle only set aRes to filterAliasListByUTI(aliasList, "com.apple.application-bundle") of me set aLen to length of aRes if aLen = 0 then return –Pick up the first element set anApp to contents of first item of aRes set aRes to getBundleIDFromPath(POSIX path of anApp) of me set pListName to aRes & ".plist" set prefPath to POSIX path of (path to preferences) & pListName set aExt to current application’s NSFileManager’s defaultManager()’s fileExistsAtPath:prefPath if aExt = true then revealAFileByFinder(prefPath) of me end if on filterAliasListByUTI(aliasList as list, acceptUTI as string) set fList to {} repeat with i in aliasList set aUTI to getUTIfromPath(i) of me if aUTI is not equal to missing value then set uRes to filterUTIList({aUTI}, acceptUTI) of me if uRes is not equal to {} then set the end of fList to contents of i end if end if end repeat return fList end filterAliasListByUTI –Application path –> Bundle ID on getBundleIDFromPath(aPOSIXpath as string) set aURL to current application’s |NSURL|’s fileURLWithPath:aPOSIXpath set aWorkspace to current application’s NSWorkspace’s sharedWorkspace() set appURL to aWorkspace’s URLForApplicationToOpenURL:aURL set aBundle to current application’s NSBundle’s bundleWithURL:appURL set anID to aBundle’s bundleIdentifier() return anID as string end getBundleIDFromPath on revealAFileByFinder(aPOSIXpath as string) set pathStr to current application’s NSString’s stringWithString:aPOSIXpath set parentPath to pathStr’s stringByDeletingLastPathComponent() set aRes to current application’s NSWorkspace’s sharedWorkspace()’s selectFile:pathStr inFileViewerRootedAtPath:parentPath end revealAFileByFinder –Alias –> UTI on getUTIfromPath(anAlias) set aPOSIXpath to POSIX path of anAlias set aURL to current application’s |NSURL|’s fileURLWithPath:aPOSIXpath if aURL = missing value then return missing value set aRes to aURL’s resourceValuesForKeys:{current application’s NSURLTypeIdentifierKey} |error|:(missing value) if aRes = missing value then return missing value return (aRes’s NSURLTypeIdentifierKey) as string end getUTIfromPath on filterUTIList(aUTIList, aUTIstr) set anArray to NSArray’s arrayWithArray:aUTIList set aPred to NSPredicate’s predicateWithFormat_("SELF UTI-CONFORMS-TO %@", aUTIstr) set bRes to (anArray’s filteredArrayUsingPredicate:aPred) as list return bRes end filterUTIList |
Finderの環境設定で「すべてのファイル名拡張子を表示」にチェックが入っているかを確認するAppleScriptです。
iWorkアプリケーション(Keynote、Pages、Numbers)では、オープン中の書類名を返すときに、Finderの上記の環境設定の内容を反映して拡張子を含めたり、含めなかったりしつつ名称を返すという仕様。
「ファイル名単独で求めることなんてないでしょ?」と思いつつも、オープン中のドキュメントの存在確認を名称で行うため、けっこう左右されることになります。
| AppleScript名:Finder上で「すべてのファイル名拡張子を表示」にチェックが入っているかを返す.scpt |
| — – Created by: Takaaki Naganoya – Created on: 2020/05/19 — – Copyright © 2020 Piyomaru Software, All Rights Reserved — set exRes to checkDisplayTheFileExtensionsInFinder() of me –> true on checkDisplayTheFileExtensionsInFinder() try set aRes to (do shell script "/usr/bin/defaults read NSGlobalDomain AppleShowAllExtensions") as integer return aRes as boolean on error return false end try end checkDisplayTheFileExtensionsInFinder |
指定アプリケーションを、現在のユーザーアカウントで指定可能な言語環境を指定して再起動するAppleScriptの改良版です。
初版では言語環境を選んでからアプリケーションを選んでいましたが、この順番を逆にしました。アプリケーションを選択し、そのバンドル内のローカライズ状況を調べ、一覧から選択して起動します。

▲Keynoteのローカライズ言語一覧から対象言語コードを選択
個人的には割と実用性が高いScriptです。
| AppleScript名:指定アプリケーションの指定言語環境で再起動 v3.scptd |
| — – Created by: Takaaki Naganoya – Created on: 2020/05/06 — – Copyright © 2020 Piyomaru Software, All Rights Reserved — use AppleScript version "2.5" use scripting additions use framework "Foundation" property |NSURL| : a reference to current application’s |NSURL| property NSBundle : a reference to current application’s NSBundle property NSWorkspace : a reference to current application’s NSWorkspace set anApp to path to (choose application) tell application "Finder" set aBundle to properties of anApp set targID to id of aBundle –Get Bundle ID end tell set bRes to getLocalizationsFromBundleID(targID) of me set cRes to my sort1DList:bRes ascOrder:true set dRes to (choose from list cRes) if dRes = missing value or dRes = false then return set targLanguage to first item of dRes set appPath to retPathFromBundleID(targID) of me set sText to "open -n -a " & quoted form of appPath & " –args -AppleLanguages ’(\"" & targLanguage & "\")’" do shell script sText on getLocalizationsFromBundleID(aBundleID) set aRes to retPathFromBundleID(aBundleID) of me if aRes = false then error "Wrong Bundle ID." return getSpecifiedAppFilesLocalizationListWithDuplication(aRes) of me end getLocalizationsFromBundleID –指定アプリケーションファイルの、指定Localeにおけるローカライズ言語リストを求める。重複を許容 on getSpecifiedAppFilesLocalizationListWithDuplication(appPOSIXpath) set aURL to (|NSURL|’s fileURLWithPath:appPOSIXpath) set aBundle to NSBundle’s bundleWithURL:aURL set locList to aBundle’s localizations() return locList as list end getSpecifiedAppFilesLocalizationListWithDuplication on retPathFromBundleID(aBundleID) set aURL to NSWorkspace’s sharedWorkspace()’s URLForApplicationWithBundleIdentifier:aBundleID if aURL = missing value then return false –Error return aURL’s |path|() as string end retPathFromBundleID –1D Listをsort / ascOrderがtrueだと昇順ソート、falseだと降順ソート on sort1DList:theList ascOrder:aBool set aDdesc to current application’s NSSortDescriptor’s sortDescriptorWithKey:"self" ascending:aBool selector:"localizedCaseInsensitiveCompare:" set theArray to current application’s NSArray’s arrayWithArray:theList return (theArray’s sortedArrayUsingDescriptors:{aDdesc}) as list end sort1DList:ascOrder: |
Finderで選択中のファイルすべてに対して、親フォルダ名、親+1階層のフォルダ名を反映させたファイル名をつけるAppleScriptです。
Blogアーカイブ本を作るのに、こうした道具を作って使っています。一度書いておけば、2度目からは大幅に時間を短縮できます。最初のファイルから拡張子を取得してそれを後続のファイルすべてに適用するため、同一種類のファイルである必要があります。自分用のツールならではの手抜きといったところでしょうか。
| AppleScript名:BlogアーカイブのMarkdown書類をリネーム。親、親+1階層フォルダをMM, YYYYとみなして反映 .scptd |
| — Created 2020-01-18 by Takaaki Naganoya — 2020 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" –選択ファイルを取得 tell application "Finder" set aSel to selection as alias list –Select documents to Rename end tell set aCount to 10 –start set aStep to 10 set aDigit to 3 –パス情報を取得 set aFirst to first item of aSel set aPOSIX to POSIX path of aFirst set aPathStr to (current application’s NSString’s stringWithString:aPOSIX) set aDateComList to aPathStr’s pathComponents() –ディレクトリごとにパス情報を分割してリスト化 set aExt to aPathStr’s pathExtension() –拡張子 set aYear to (item -3 of aDateComList) as string –親の親フォルダ名 set aMonth to (item -2 of aDateComList) as string –親フォルダ名 –リネーム(数百項目を超える場合にはFinderでは遅すぎるのでNSFileManagerで処理) tell application "Finder" repeat with i in aSel set aTEXT to numToZeroPaddingStr(aCount, aDigit, "0") of me –3 digit set aName to aYear & aMonth & aTEXT & "." & aExt set name of i to aName set aCount to aCount + aStep end repeat end tell –整数の値に指定桁数ゼロパディングして文字列で返す on numToZeroPaddingStr(aNum as integer, aDigit as integer, paddingChar as text) set aNumForm to current application’s NSNumberFormatter’s alloc()’s init() aNumForm’s setPaddingPosition:(current application’s NSNumberFormatterPadBeforePrefix) aNumForm’s setPaddingCharacter:paddingChar aNumForm’s setMinimumIntegerDigits:aDigit set bNum to current application’s NSNumber’s numberWithInt:aNum set aStr to aNumForm’s stringFromNumber:bNum return aStr as text end numToZeroPaddingStr |
Bundle IDで指定したアプリケーションからすべてのLocaleを取得し、ダイアログ選択したLocale内のすべてのstringsファイルを読み込んでNSDictionary化して指定のキーワードを含むものを抽出するAppleScriptです。
指定キーワードが含まれていた場合には、
キー, 値, stringsファイルのパス
をリストで返します。調査のための下調べを行うものです。
| AppleScript名:指定アプリケーションの指定ロケールのフォルダ内の該当キーワードを含むstringsファイル情報を抽出する |
| — – Created by: Takaaki Naganoya – Created on: 2019/09/21 — – Copyright © 2019 Piyomaru Software, All Rights Reserved — use AppleScript version "2.5" use scripting additions use framework "Foundation" property |NSURL| : a reference to current application’s |NSURL| property NSArray : a reference to current application’s NSArray property NSBundle : a reference to current application’s NSBundle property NSPredicate : a reference to current application’s NSPredicate property NSDictionary : a reference to current application’s NSDictionary property NSWorkspace : a reference to current application’s NSWorkspace property NSFileManager : a reference to current application’s NSFileManager property NSMutableDictionary : a reference to current application’s NSMutableDictionary property NSURLTypeIdentifierKey : a reference to current application’s NSURLTypeIdentifierKey property NSDirectoryEnumerationSkipsHiddenFiles : a reference to current application’s NSDirectoryEnumerationSkipsHiddenFiles property NSDirectoryEnumerationSkipsPackageDescendants : a reference to current application’s NSDirectoryEnumerationSkipsPackageDescendants set targID to "com.apple.Finder" set targWords to "のコピー" set bRes to getLocalizationsFromBundleID(targID) of me –> {"de", "he", "en_AU", "ar", "el", "ja", "en", "uk", "es_419", "zh_CN", "es", "da", "it", "sk", "pt_PT", "ms", "sv", "cs", "ko", "Base", "no", "hu", "zh_HK", "tr", "pl", "zh_TW", "en_GB", "vi", "ru", "fr_CA", "fr", "fi", "id", "nl", "th", "pt", "ro", "hr", "hi", "ca"} –Select Localization set curLang to first item of (choose from list bRes) –Get All strings file path within a bundle set aPath to retPathFromBundleID(targID) of me set aPath to aPath & "/Contents/Resources/" & curLang & ".lproj" set sList to getFilepathListByUTI(aPath, "com.apple.xcode.strings-text", "POSIX") of me –Get Every Key & Value pair then filter target keyword set aMDict to NSMutableDictionary’s new() set hitList to {} repeat with ii in sList set jj to contents of ii set aDict to (NSDictionary’s alloc()’s initWithContentsOfFile:jj) (aMDict’s addEntriesFromDictionary:aDict) set kList to aMDict’s allKeys() as list set vList to aMDict’s allValues() as list set kCount to 1 repeat with i in vList set j to contents of i if j contains targWords then set the end of hitList to {contents of item kCount of kList, j, jj} end if set kCount to kCount + 1 end repeat end repeat return hitList –> {{"PW5_V2", "^0項目のコピーの準備中", "/System/Library/CoreServices/Finder.app/Contents/Resources/Japanese.lproj/Localizable.strings"}, …} on getLocalizationsFromBundleID(aBundleID) set aRes to retPathFromBundleID(aBundleID) of me if aRes = false then error "Wrong Bundle ID." return getSpecifiedAppFilesLocalizationListWithDuplication(aRes) of me end getLocalizationsFromBundleID –指定アプリケーションファイルの、指定Localeにおけるローカライズ言語リストを求める。重複を許容 on getSpecifiedAppFilesLocalizationListWithDuplication(appPOSIXpath) set aURL to (|NSURL|’s fileURLWithPath:appPOSIXpath) set aBundle to NSBundle’s bundleWithURL:aURL set locList to aBundle’s localizations() return locList as list end getSpecifiedAppFilesLocalizationListWithDuplication on retPathFromBundleID(aBundleID) set aURL to NSWorkspace’s sharedWorkspace()’s URLForApplicationWithBundleIdentifier:aBundleID if aURL = missing value then return false –Error return aURL’s |path|() as string end retPathFromBundleID on getFilepathListByUTI(aFolPOSIX, aUTI as string, aFileType as string) script spdFile property urlList : {} end script if aFileType is not in {"file", "POSIX"} then return {} set aFM to NSFileManager’s defaultManager() set aFolExt to (aFM’s fileExistsAtPath:aFolPOSIX isDirectory:true) as boolean if aFolExt = false then return {} –フォルダ自体が存在しなければヌルリストを返す set aURL to |NSURL|’s fileURLWithPath:aFolPOSIX set theOptions to ((NSDirectoryEnumerationSkipsPackageDescendants) as integer) + ((NSDirectoryEnumerationSkipsHiddenFiles) as integer) set urlArray to (aFM’s contentsOfDirectoryAtURL:aURL includingPropertiesForKeys:{} options:theOptions |error|:(missing value)) if urlArray = missing value then return {} set (urlList of spdFile) to urlArray as list set newList to {} repeat with i in (urlList of spdFile) set j to POSIX path of i set tmpUTI to my retUTIfromPath(j) set utiRes to my filterUTIList({tmpUTI}, aUTI) if utiRes is not equal to {} then if aFileType = "POSIX" then set the end of newList to j else if aFileType = "file" then set the end of newList to POSIX file j end if end if end repeat return newList end getFilepathListByUTI –指定のPOSIX pathのファイルのUTIを求める on retUTIfromPath(aPOSIXPath) set aURL to |NSURL|’s fileURLWithPath:aPOSIXPath set {theResult, theValue} to aURL’s getResourceValue:(reference) forKey:NSURLTypeIdentifierKey |error|:(missing value) if theResult = true then return theValue as string else return theResult end if end retUTIfromPath –UTIリストが指定UTIに含まれているかどうか演算を行う on filterUTIList(aUTIList, aUTIstr) set anArray to NSArray’s arrayWithArray:aUTIList set aPred to NSPredicate’s predicateWithFormat_("SELF UTI-CONFORMS-TO %@", aUTIstr) set bRes to (anArray’s filteredArrayUsingPredicate:aPred) as list return bRes end filterUTIList |
Bundle IDで指定したアプリケーションのバンドル中(/Contents/Resources/)のすべてのLocalizationに存在する指定のstringsファイル内で、指定キーの値を取得するAppleScriptです。
macOSの日本語環境では、Finder上でコピーしたファイルのファイル名の後方に「のコピー」といった文字列が追記されますが、他のLocaleでどのような文字列が使用されているか調査するために作成したものです。
| AppleScript名:指定アプリケーション内の全Localeの指定stringsファイル内の指定キーの値を取得する.scptd |
| — – Created by: Takaaki Naganoya – Created on: 2019/11/12 — – Copyright © 2019 Piyomaru Software, All Rights Reserved — use AppleScript version "2.5" use scripting additions use framework "Foundation" property |NSURL| : a reference to current application’s |NSURL| property NSArray : a reference to current application’s NSArray property NSBundle : a reference to current application’s NSBundle property NSPredicate : a reference to current application’s NSPredicate property NSDictionary : a reference to current application’s NSDictionary property NSWorkspace : a reference to current application’s NSWorkspace property NSFileManager : a reference to current application’s NSFileManager property NSMutableDictionary : a reference to current application’s NSMutableDictionary property NSURLTypeIdentifierKey : a reference to current application’s NSURLTypeIdentifierKey set targID to "com.apple.Finder" set targFile to "Localizable.strings" set targKey to "N4_V2" set vList to getAValInASpecifiedStringFileOfAllLocaleInABundle(targID, targFile, targKey) of me –> {{"he", "עותק של ^=1 ^=0"}, {"en_AU", "^=1 copy ^=0"}, {"ar", "نسخة ^=0 من ^=1"}, {"el", "^=1 αντίγραφο ^=0"}, {"uk", "^=1 копія ^=0"}, {"English", "^=1 copy ^=0"}, {"es_419", "Copia de ^=1 ^=0"}, {"zh_CN", "^=1的副本 ^=0"}, {"Dutch", "^=1 kopie ^=0"}, {"da", "^=1-kopi ^=0"}, {"sk", "^=1 – kópia ^=0"}, {"pt_PT", "^=1 – cópia ^=0"}, {"German", "^=1 Kopie ^=0"}, {"ms", "salinan ^=0 ^=1"}, {"sv", "^=1 (kopia ^=0)"}, {"cs", "^=1 (kopie ^=0)"}, {"ko", "^=1 복사본 ^=0"}, {"no", "^=1-kopi ^=0"}, {"hu", "^=1 másolat ^=0"}, {"zh_HK", "^=1 副本 ^=0"}, {"Spanish", "^=1 copia ^=0"}, {"tr", "^=1 kopyası ^=0"}, {"pl", "^=1-kopia ^=0"}, {"zh_TW", "^=1 拷貝 ^=0"}, {"en_GB", "^=1 copy ^=0"}, {"French", "^=1 copie ^=0"}, {"vi", "Bản sao ^=1 ^=0"}, {"ru", "^=1 — копия ^=0"}, {"fr_CA", "^=1 copie ^=0"}, {"fi", "^=1 kopio ^=0"}, {"id", "Salinan ^=1 ^=0"}, {"th", "^=1 สำเนา ^=0"}, {"pt", "^=1 – cópia ^=0"}, {"ro", "^=1 – copie ^=0"}, {"Japanese", "^=1のコピー^=0"}, {"hr", "^=1 kopija ^=0"}, {"hi", "^=1 कॉपी ^=0"}, {"Italian", "^=1 copia ^=0"}, {"ca", "^=1 còpia ^=0"}} on getAValInASpecifiedStringFileOfAllLocaleInABundle(targID, targFile, targKey) –Get App Path set aPath to retPathFromBundleID(targID) of me –Get all Localizations set bRes to getLocalizationsFromBundleID(targID) of me set hitList to {} –Loop with Localizations in an application bundle repeat with iii in bRes set jjj to contents of iii set allPath to aPath & "/Contents/Resources/" & jjj & ".lproj/" & targFile set aDict to (NSDictionary’s alloc()’s initWithContentsOfFile:allPath) if aDict is not equal to missing value then set aVal to (aDict’s valueForKeyPath:(targKey)) if aVal is not equal to missing value then set the end of hitList to {jjj, aVal as string} end if end if end repeat return hitList end getAValInASpecifiedStringFileOfAllLocaleInABundle on getLocalizationsFromBundleID(aBundleID) set aRes to retPathFromBundleID(aBundleID) of me if aRes = false then error "Wrong Bundle ID." return getSpecifiedAppFilesLocalizationListWithDuplication(aRes) of me end getLocalizationsFromBundleID –指定アプリケーションファイルの、指定Localeにおけるローカライズ言語リストを求める。重複を許容 on getSpecifiedAppFilesLocalizationListWithDuplication(appPOSIXpath) set aURL to (|NSURL|’s fileURLWithPath:appPOSIXpath) set aBundle to NSBundle’s bundleWithURL:aURL set locList to aBundle’s localizations() return locList as list end getSpecifiedAppFilesLocalizationListWithDuplication on retPathFromBundleID(aBundleID) set aURL to NSWorkspace’s sharedWorkspace()’s URLForApplicationWithBundleIdentifier:aBundleID if aURL = missing value then return false –Error return aURL’s |path|() as string end retPathFromBundleID |
関数計算機能をAppleScriptに提供するAppleScriptライブラリ「calcLibAS」をアップデートしてみました。
変更点:
・sdefを書いたので、各種関数が予約語で呼び出せるようになった
だけです。
–> Download calcLibASv1.5 (To ~/Library/Script Libraries/)

さまざまな関数計算の機能をAppleScriptに提供するモジュールと比べてもサポート関数の数が多く、さらに本ライブラリは単にJavaScriptCoreの関数計算機能を変換しているだけなので、ライブラリ内で計算は一切していません。
技術的に何も見るべき点がなく、高度なテーマに一切挑戦していないのに、大量の数値関数の機能を提供しているのが本ライブラリの特徴です。志の低さでは他に類を見ないレベルですが、実際に稼働して役に立っています。
本来はCephes Math Library(関数36個ぐらい)あたりをラッピングしようと考えていたのですが、JavaScriptCore経由でJavaScript(おそらくCephes Math Libraryをラッピング)の関数を呼び出してもほぼ同数の関数が使えることが判明したため、3時間ぐらいで作ってみたのがはじまりです。当初のバージョンはJXAで記述した計算ルーチンを呼び出していましたが、JXAが頻繁にクラッシュしたため、JavaScriptCoreを呼び出すように変更・高速化(最初のバージョンから28倍速)しました。
ハンドラ呼び出しとsdefによる予約語を通じて関数計算した場合で、計算精度などに差は出ていないことを内部の検証コマンドで確認してあります。
メンテナンスしやすいように、sdefからの呼び出しサービスを行うライブラリと実際の計算(呼び出し)を行うCoreライブラリの2つの部品に分けています。機能本体部分にsdefで定義した予約語を使うと、メンテナンスも何もできなくなるというapplescript-stdlibを反面教師とし、さらにsdefからの呼び出し部分がパラメータのチェックや例外処理への対応などで容易に機能がふくれあがっていくため、メンテナンス性を確保するためにこのような構造にしました。
log関数については、すでにAppleScriptビルトインで、まったく異なる働きを行うlogコマンド(スクリプトエディタ/Script Debuggerのログ表示機能でログ表示)があるので、重複を避けるためにsdef定義でlogarithmと表記するようにしました。
roundも同様にsdef定義でroundNumと表記しています。
実際に、三角関数やatan2などの関数を使い出していますが、精度や挙動、実行速度などに前バージョンから差異はありません。AppleScript用語の予約語がついて呼びやすくなっただけです。
| AppleScript名:Every Functions |
| — Created 2019-08-20 by Takaaki Naganoya — 2019 Piyomaru Software use AppleScript version "2.5" use scripting additions use framework "Foundation" use calSub : script "calcLibAS" set a001 to abs -10 set a002 to acos -1 set a003 to acosh 10 set a004 to asin 10 set a005 to asinh 10 set a006 to atan 10 set a007 to atan2 {10, 20} set a008 to atanh 10 set a009 to cbrt 3 set a010 to ceil 0.95 set a011 to clz32 1 set a012 to cos 1 set a013 to cosh 1 set a014 to exp 1 set a015 to expm1 -1 set a016 to floor 45.95 set a017 to fround 1.337 set a018 to hypot {3, 4, 5} set a019 to lmul {2, 5} set a020 to logarithm 10 set a021 to log10 2 set a022 to log1p 1 set a023 to log2 3 set a024 to max {1, 2, 3, 4, 6, 2, 10} set a025 to min {1, 2, 3, 4, 6, 2, 10, 0} set a026 to pow {7, 2} set a027 to rnd –random number set a028 to roundNum 5.95 set a029 to sign 10 set a030 to sin (pi / 2) set a031 to sinh 1 set a032 to sqrt 2 set a033 to tan 30 set a034 to tanh 10 set a035 to trunc 13.37 set aList to {a001, a002, a003, a004, a005, a006, a007, a008, a009, a010, a011, a012, a013, a014, a015, a016, a017, a018, a019, a020, a021, a022, a023, a024, a025, a026, a027, a028, a029, a030, a031, a032, a033, a034, a035} return test() of calSub –Check function to calc from sdef and each handlers excepting random numbers |
| AppleScript名:Calc direction from place A to B |
| — Created 2019-08-20 by Takaaki Naganoya — 2017-2019 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use script "calcLibAS" set coord1 to {latitude:35.73677496, longitude:139.63754457} –Nakamurabashi Sta. set coord2 to {latitude:35.78839012, longitude:139.61241447} –Wakoshi Sta. set dirRes1 to calcDirectionBetweenTwoPlaces(coord1, coord2) of me –> -25.925429877542 set coord2 to {latitude:35.7227821, longitude:139.63860897} –Saginomiya Sta. set dirRes2 to calcDirectionBetweenTwoPlaces(coord1, coord2) of me –> 175.649833487804 set coord2 to {latitude:35.73590542, longitude:139.62986745} –Fujimidai Sta. set dirRes3 to calcDirectionBetweenTwoPlaces(coord1, coord2) of me –> -96.385293928667 set coord2 to {latitude:35.73785024, longitude:139.65339321} –Nerima Sta. set dirRes4 to calcDirectionBetweenTwoPlaces(coord1, coord2) of me –> 85.959474671834 set coord2 to {latitude:35.71026838, longitude:139.81215754} –Tokyo Sky Tree set dirRes5 to calcDirectionBetweenTwoPlaces(coord1, coord2) of me –> 96.826542737106 –位置情報1から位置情報2の方角を計算。北が0度 on calcDirectionBetweenTwoPlaces(coord1, coord2) set deltaLong to (longitude of coord2) – (longitude of coord1) set yComponent to sin deltaLong set xComponent to (cos (latitude of coord1)) * (sin (latitude of coord2)) – (sin (latitude of coord1)) * (cos (latitude of coord2)) * (cos deltaLong) set radians to (atan2 {yComponent, xComponent}) as real set degreeRes to (radToDeg(radians) of me) return degreeRes end calcDirectionBetweenTwoPlaces on radToDeg(aRadian) return aRadian * (180 / pi) end radToDeg |
| AppleScript名:日本測地系から世界測地系への座標変換.scpt |
| — Created 2018-07-13 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use math : script "calcLibAS" set jpLat to 42.16593046887 set jpLng to 142.771877437246 set {wdLat, wdLng, wdH} to JapanGeodeticSystem’s convertIntoWgs(jpLat, jpLng) –> {42.168504277889, 142.768075650137, 61.914452206343} –https://altarf.net/computer/ruby/3347 –日本測地系から世界測地系に換算 script JapanGeodeticSystem –ラジアン(度) property rdNum : pi / 180 –日本測地系の定数(ベッセル楕円体) property rJP : 6.377397155E+6 –赤道半径 property fJP : 1 / 299.1528128 –扁平率 property e2JP : (2 * fJP) – (fJP * fJP) –第一離心率 –世界測地系の定数(WGS84) property rWS : 6.378137E+6 –赤道半径 property fWS : 1 / 298.257223563 –扁平率 property e2WS : (2 * fWS) – (fWS * fWS) –第一離心率 –並行移動量(m) property dxNum : -148 property dyNum : 507.0 property dzNum : 681.0 –楕円体高 property heightNum : 0 –日本測地系から世界測地系に変換する on convertIntoWgs(aLat, aLong) set {x, y, z} to llh2xyz(aLat, aLong, heightNum, rJP, e2JP, rdNum) of me set x to x + dxNum set y to y + dyNum set z to z + dzNum set {lat1, lng1, h1} to xyz2llh(x, y, z, rWS, e2WS, rdNum) of me return {lat1, lng1, h1} end convertIntoWgs –座標系の変換(緯度経度 -> xyz) on llh2xyz(latLocal, lngLocal, hLocal, aLocal, e2Local, rdLocal) set latLocal to latLocal * rdLocal set lngLocal to lngLocal * rdLocal set sbNum to sin latLocal set cbNum to cos latLocal set rnLocal to aLocal / (sqrt (1 – e2Local * sbNum * sbNum)) set xLocal to (rnLocal + hLocal) * cbNum * (cos lngLocal) set yLocal to (rnLocal + hLocal) * cbNum * (sin lngLocal) set zLocal to (rnLocal * (1 – e2Local) + hLocal) * sbNum return {xLocal, yLocal, zLocal} end llh2xyz –座標系の変換(xyz -> 緯度経度) on xyz2llh(x, y, z, a, e2, rdLocal) set bda to sqrt (1 – e2) set p to sqrt (x * x + y * y) set t to atan2 {z, p * bda} set stNum to sin (t) set ctNum to cos (t) set b to atan2 {z + e2 * a / bda * stNum * stNum * stNum, p – e2 * a * ctNum * ctNum * ctNum} set l to atan2 {y, x} set sb to sin (b) set rn to a / (sqrt (1 – e2 * sb * sb)) set h to p / (cos (b)) – rn set l1 to b / rdLocal set l2 to l / rdLocal return {l1, l2, h} end xyz2llh end script |
| AppleScript名:Circulate Finder windows |
| — Created 2014-11-17 by Takaaki Naganoya — Modified 2019-08-18 by Takaaki Naganoya — 2014-2019 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" — for NSScreen use calLib : script "calcLibAS" property aNum : 300 property aOffset : 0 property maxWin : 6 property winList : {} property randList : {} property winSize : 300 –Initialize set winList to {} set randList to {} repeat maxWin times tell application "Finder" activate set aWin to make new Finder window tell aWin set toolbar visible to false set sidebar width to 0 set statusbar visible to false set position to {100, 100} set bounds to {100, 100, 100 + winSize, 100 + winSize} end tell set the end of winList to aWin set the end of randList to {random number from 0 to 400, random number from 0 to 400, random number from 1 to 360} end tell end repeat –Main repeat with i from 1 to 360 by 6 repeat with ii from 1 to maxWin set aWinObj to contents of item ii of winList set {aRandX, aRandY, aRandDegree} to item ii of randList set aDeg to i + aRandDegree set aSinNum to (sin aDeg) as real set aCosNum to (cos aDeg) as real set x to ((aNum * aSinNum) + aNum) * 2 + aOffset set y to (aNum * aCosNum) + aNum + aOffset ignoring application responses tell application "Finder" tell aWinObj set position to {(x as integer) + aRandX, (y as integer) + aRandY} end tell end tell end ignoring end repeat end repeat –Sweep tell application "Finder" repeat with i in winList tell i close end tell end repeat end tell |
| AppleScript名:2点間の距離を求める(地球を球体として計算) |
| — Created 2019-08-22 by Takaaki Naganoya use AppleScript version "2.5" use scripting additions use framework "Foundation" use script "calcLibAS" property earth_radius : 6378140 set aPoint to {lat:35.7398693, long:139.6474103} set bPoint to {lat:31.5719562, long:130.56257084} set aRes to calcDistanceBetweenTwoPoint(aPoint, bPoint) of me on calcDistanceBetweenTwoPoint(aPoint, bPoint) set lat1 to lat of aPoint set lng1 to long of aPoint set lat2 to lat of bPoint set lng2 to long of bPoint –緯度経度をラジアンに変換 set rlat1 to lat1 * pi / 180 set rlng1 to lng1 * pi / 180 set rlat2 to lat2 * pi / 180 set rlng2 to lng2 * pi / 180 — 2点の中心角(ラジアン)を求める set a to (sin rlat1) * (sin rlat2) + (cos rlat1) * (cos rlat2) * (cos rlng1 – rlng2) set rr to acos a –2点間の距離(メートル) set distance to earth_radius * rr return distance end calcDistanceBetweenTwoPoint |
Keynoteでオープン中の最前面の書類で、選択中のスライドだけをデスクトップにPNG画像で書き出すAppleScriptです。Keynote 9.xを必要とします(macOS 10.13以降)。
ちょっとした説明のためにKeynoteの資料の一部だけを画面上でキャプチャして、メールなどに添付して送ることはよくあります(全部送ると量がおおすぎたり、焦点がぼやけたり)。

そこで、複数枚のスライド(ページ)を選択しておくと、それらのみを画像書き出しするAppleScriptを作ってみました。Keynoteにそんな機能はないのですが、「選択中のページ番号」は取れるので、書類全体をPDF書き出ししておいて、書き出したPDFから指定ページを画像として再書き出しを行い、PDFを削除しています。
手品のように見える処理でも、実際に行える機能を組み合わせて地道に作っているだけです。問題は、「手品」が実は地道な調査と機能確認、こまごまとしたライブラリの整備の末に実現されていることが、一般の方にはわかりにくいということでしょうか(いきなり手品を求められて絶句すること多し)。

仕事の合間に作ったので、割と雑な作りです。書き出し画像のファイル名衝突チェックなどは入れていません。
それでも、スクリプトメニューに入れて利用するとなかなか便利です。

| AppleScript名:Keynoteで選択中のスライドだけをデスクトップに画像で書き出す.scptd |
| — – Created by: Takaaki Naganoya – Created on: 2019/06/20 — – Copyright © 2019 Piyomaru Software, All Rights Reserved — use AppleScript version "2.7" — 10.13 or later use framework "Foundation" use framework "Quartz" use framework "AppKit" use scripting additions set dtPath to (path to desktop) as string tell application "Keynote" set aVer to version considering numeric strings if aVer < "9.0" then display dialog "Too old version for this Script." buttons {"OK"} default button 1 with icon 1 return end if end considering tell front document set aSel to selection –選択中のスライドオブジェクトへの参照がリストで入る set pList to {} repeat with i in aSel set tmpPage to slide number of i set the end of pList to tmpPage end repeat end tell end tell –Keynote書類を指定フォルダにPDF書き出し(全ページ書き出し) set savedPDFPath to exportKeynoteDocToPDF(dtPath) of me if savedPDFPath = false then return –Error set aPOSIXpath to POSIX path of savedPDFPath –書き出したPDFから、部分的にPNG画像に書き出す repeat with p in pList –PDFの指定ページをNSImageとして取り出す set tmpNSImage to getNSImageFromPDFPage(aPOSIXpath, p) of me –PDFの書き出しファイル名に子番号にスライド番号をつける set bPath to addStringbeforeExtension(aPOSIXpath, "_" & (p as string)) of me –PDF書き出しファイル名に set newPath to repFilePathExtension(bPath, ".png") of me –指定のNSImageを指定のパスにPNG形式で保存 set sRes to saveNSImageAtPathAsPNG(tmpNSImage, newPath) of me end repeat –書き出したPDFを削除 tell application "Finder" delete savedPDFPath end tell –Keynote書類からPDF書き出し on exportKeynoteDocToPDF(targFolderPath as string) tell application "Keynote" set dCount to count every document if dCount = 0 then return false end if set aPath to file of document 1 end tell set curPath to (current application’s NSString’s stringWithString:(POSIX path of aPath))’s lastPathComponent()’s stringByDeletingPathExtension()’s stringByAppendingString:".pdf" set outPath to (targFolderPath & curPath) tell application "Keynote" set anOpt to {class:export options, export style:IndividualSlides, all stages:false, skipped slides:true, PDF image quality:Best} export document 1 to file outPath as PDF with properties anOpt end tell return (outPath as alias) end exportKeynoteDocToPDF –指定のPDFから、指定のページをNSImageで返す on getNSImageFromPDFPage(aPOSIX, aPage as number) set aURL to (current application’s |NSURL|’s fileURLWithPath:aPOSIX) set aPDFdoc to current application’s PDFDocument’s alloc()’s initWithURL:aURL set pCount to aPDFdoc’s pageCount() set compFactor to 1.0 –1.0 — 0.0 = max jpeg compression, 1.0 = none –Detect Retina Environment set retinaF to current application’s NSScreen’s mainScreen()’s backingScaleFactor() if retinaF = 1.0 then set aScale to 2.0 –Non Retina Env else set aScale to 1.0 –Retina Env end if set thisPage to (aPDFdoc’s pageAtIndex:(aPage – 1)) set anNSImage to (current application’s NSImage’s alloc()’s initWithData:(thisPage’s dataRepresentation())) if anNSImage = missing value then error "Error in getting imagerep from PDF" return anNSImage end getNSImageFromPDFPage –ファイル名の拡張子の直前に子番号的な文字列を入れる on addStringbeforeExtension(aPath, extraString) set pathString to current application’s NSString’s stringWithString:aPath set theExtension to pathString’s pathExtension() set thePathNoExt to pathString’s stringByDeletingPathExtension() set newPath to (thePathNoExt’s stringByAppendingString:extraString)’s stringByAppendingPathExtension:theExtension return newPath as string end addStringbeforeExtension –与えられたパスの拡張子を付け替える on repFilePathExtension(origPath, newExt) set aName to current application’s NSString’s stringWithString:origPath set theExtension to aName’s pathExtension() if (theExtension as string) is not equal to "" then set thePathNoExt to aName’s stringByDeletingPathExtension() set newName to (thePathNoExt’s stringByAppendingString:newExt) else set newName to (aName’s stringByAppendingString:newExt) end if return newName as string end repFilePathExtension –NSImageを指定パスにPNG形式で保存 on saveNSImageAtPathAsPNG(anImage, outPath) set imageRep to anImage’s TIFFRepresentation() set aRawimg to current application’s NSBitmapImageRep’s imageRepWithData:imageRep set pathString to current application’s NSString’s stringWithString:outPath set newPath to pathString’s stringByExpandingTildeInPath() set myNewImageData to (aRawimg’s representationUsingType:(current application’s NSPNGFileType) |properties|:(missing value)) set aRes to (myNewImageData’s writeToFile:newPath atomically:true) as boolean return aRes –true/false end saveNSImageAtPathAsPNG |
CotEditorで編集中のMarkdown書類を、MacDownでPDF書き出しして、Skimでオープンして表示するAppleScriptです。
CotEditorにMarkdownのプレビュー機能がついたらいいと思っている人は多いようですが、MarkdownはMarkdownで、方言は多いし標準がないし、1枚もののMarkdown書類だけ編集できればいいのか、本などのプロジェクト単位で編集とか、目次が作成できないとダメとか、リンクした画像の扱いをどうするのかとか、対応しようとすると「ほぼ別のソフトを作るのと同じ」ぐらい手間がかかりそうです(メンテナー様ご本人談)。
そこで、AppleScript経由で他のソフトを連携させてPDFプレビューさせてみました。これなら、誰にも迷惑をかけずに、今日この時点からすぐにMarkdownのプレビューが行えます(当然、HTML書き出ししてSafariでプレビューするバージョンははるかかなた昔に作ってあります)。
ただし、OS側の機能制限の問題で、CotEditor上のスクリプトメニューから実行はできません(GUI Scriptingの実行が許可されない)。OS側のスクリプトメニューに登録して実行する必要があります。
GUI Scriptingを利用してメニュー操作を行なっているため、システム環境設定で許可しておく必要があります。
本来であれば、PDFの書き出し先フォルダ(この場合は書き出しダイアログで、GUI Scirptingを用いてCommand-Dで指定して一律に場所指定が行えるデスクトップフォルダ)に同名のPDFが存在しないかどうかチェックし、存在すれば削除するといった処理が必要ですが、面倒だったのであらかじめMarkdown書類をUUIDにリネームしておくことで、書き出されたPDFも同じくUUIDのファイル名になるため、論理上はファイル名の衝突を回避できるため、削除処理を省略しています。

| AppleScript名:🌏レンダリングしてPDFプレビュー |
| — Created 2019-06-15 by Takaaki Naganoya — 2019 Piyomaru Software use AppleScript version "2.5" use scripting additions use framework "Foundation" use framework "AppKit" property NSUUID : a reference to current application’s NSUUID property NSWorkspace : a reference to current application’s NSWorkspace –オープン中のMarkdown書類を取得する tell application "CotEditor" tell front document set cStyle to coloring style if cStyle is not equal to "Markdown" then display dialog "編集中のファイルはMarkdown書類ではないようです。" buttons {"OK"} default button 1 return end if set aPath to path end tell end tell –一時フォルダにMarkdown書類をコピー set sPath to (path to temporary items) tell application "Finder" set sRes to (duplicate ((POSIX file aPath) as alias) to folder sPath with replacing) end tell –コピーしたMarkdown書類をリネーム set s1Res to sRes as alias set aUUID to NSUUID’s UUID()’s UUIDString() as text –UUIDを作成する tell application "Finder" set name of s1Res to (aUUID & ".md") end tell –Markdown書類をデスクトップにPDF書き出し set pdfRes to exportFromMacDown(POSIX path of s1Res) of me –PDF Viewerでオープン tell application "Skim" –Preview.appでもOK activate open pdfRes end tell –一時フォルダに書き出したMarkdown書類を削除 tell application "Finder" delete s1Res end tell –指定のMacDownファイル(alias)をデスクトップ上にPDFで書き出し on exportFromMacDown(anAlias) set s1Text to paragraphs of (do shell script "ls ~/Desktop/*.pdf") –pdf書き出し前のファイル一覧 tell application "MacDown" open {anAlias} end tell macDownForceSave() of me tell application "MacDown" close every document without saving end tell do shell script "sync" –ねんのため set s2Text to paragraphs of (do shell script "ls ~/Desktop/*.pdf") –pdf書き出し後のファイル一覧 set dRes to getDiffBetweenLists(s1Text, s2Text) of me –デスクトップ上のPDFファイル名一覧の差分を取得 set d2Res to (addItems of dRes) if length of d2Res ≥ 1 then return contents of first item of d2Res else error "Error in exporting PDF to desktop folder…." end if end exportFromMacDown on getDiffBetweenLists(aArray as list, bArray as list) set allSet to current application’s NSMutableSet’s setWithArray:aArray allSet’s addObjectsFromArray:bArray –重複する要素のみ抜き出す set duplicateSet to current application’s NSMutableSet’s setWithArray:aArray duplicateSet’s intersectSet:(current application’s NSSet’s setWithArray:bArray) –重複部分を削除する allSet’s minusSet:duplicateSet set resArray to (allSet’s allObjects()) as list set aSet to current application’s NSMutableSet’s setWithArray:aArray set bSet to current application’s NSMutableSet’s setWithArray:resArray aSet’s intersectSet:bSet –積集合 set addRes to aSet’s allObjects() as list set cSet to current application’s NSMutableSet’s setWithArray:bArray cSet’s intersectSet:bSet –積集合 set minusRes to cSet’s allObjects() as list return {addItems:minusRes, minusItems:addRes} end getDiffBetweenLists –注意!! ここでGUI Scriptingを使用。バージョンが変わったときにメニュー階層などの変更があったら書き換え on macDownForceSave() activate application "MacDown" tell application "System Events" tell process "MacDown" — File > Export > PDF click menu item 2 of menu 1 of menu item 14 of menu 1 of menu bar item 3 of menu bar 1 –Go to Desktop Folder keystroke "d" using {command down} –Save Button on Sheet click button 1 of sheet 1 of window 1 end tell end tell end macDownForceSave –Bundle IDからアプリケーションのPathを返す on retAppAbusolutePathFromBundleID(aBundleID) set appPath to NSWorkspace’s sharedWorkspace()’s absolutePathForAppBundleWithIdentifier:aBundleID if appPath = missing value then return false return appPath as string end retAppAbusolutePathFromBundleID |