Archive for 6月, 2012

2012/06/30 任意の桁数の2進数文字列を10進数に戻す

任意の桁数の2進数文字列を10進数に戻す(デコード)AppleScriptです。

8ビットの範囲のデコーダだけでは不便だったので、改良してみました。

スクリプト名:任意の桁数の2進数文字列を10進数に戻す
set aStr to "111110111100110000110100"
set aNum to binaryDecodeNdigit(aStr) of me
–> 16501812

–任意の桁数の2進数文字列を10進数に戻す
on binaryDecodeNdigit(aStr)
  
  
set aLen to length of aStr
  
  
set aNum to 0
  
repeat with i from (aLen - 1) to 0 by -1
    set aCon to contents of character (aLen - i) of aStr
    
    
if aCon = "1" then
      set aNum to aNum + (2 ^ i)
    end if
    
  end repeat
  
  
return aNum as integer
  
end binaryDecodeNdigit

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

2012/06/30 データの16進ダンプ(PPC_Intel、10.6以降対応) v3

データの16進数ダンプを行うAppleScriptです。変数に入れて指定したデータの内容をHexダンプします。

Mac OS X 10.6以降でhexdumpコマンドのデフォルト状態の動作が10.6以降で変わっていたことに気づかなかったのですが、10.7で動作内容が変わっているというレポートが来て調査してみた次第です。

割と……登場する頻度は高くなく、たまーに使う程度でしょうか。

スクリプト名:データの16進ダンプ(PPC_Intel対応) v3
set aData to “あいうえお”
set bData to hexDumpStr(aData) of me
bData
–> “82a082a282a482a682a8″

–データの16進ダンプ(PPC/Intel対応) v3
–Mac OS X 10.6以降でデフォルト時の動作が異なる点を解決(-x オプションを付ける必要がある)
on hexDumpStr(aData)
  –バイトオーダーを取得(1234でIntel系、4321でPPC系)
  
set byteOrder to do shell script “sysctl -n hw.byteorder”
  
  
–データの書き出し準備
  
set tmpPath to path to temporary items from user domain
  
set inData to (tmpPath as string) & “.hexdumpData.txt”
  
set inDataPosix to quoted form of POSIX path of inData
  
  
set aData to aData as Unicode text
  
set cList to characters of aData
  
  
set hexData to “”
  
  
write_to_file(aData, inData, false) of me
  
  
try
    set aRes to do shell script “/usr/bin/hexdump -x “ & inDataPosix –”-x”オプションを明示的に指定
  on error
    return “”
  end try
  
  
set aaList to paragraphs of aRes
  
copy items 1 thru -2 of aaList to bList
  
  
set hexText to “”
  
repeat with i in bList
    set j to contents of i
    
    
set aLine to text 9 thru -1 of j
    
set aWordsList to words of aLine
    
    
repeat with ii in aWordsList
      set jj to contents of ii
      
      
set firstByte to text 1 thru 2 of jj
      
set secondByte to text 3 thru 4 of jj
      
      
if byteOrder = “4321″ then
        –PPC (Big Endian)
        
if firstByte = “00″ then set firstByte to “”
        
set byteT to firstByte & secondByte
      else if byteOrder = “1234″ then
        –Intel (Little Endian )
        
if secondByte = “00″ then set secondByte to “”
        
set byteT to secondByte & firstByte
      end if
      
      
set hexData to hexData & byteT
      
    end repeat
  end repeat
  
  
return hexData
  
end hexDumpStr

–ファイルの追記ルーチン「write_to_file」
–追記データ、追記対象ファイル、boolean(trueで追記)
on write_to_file(this_data, target_file, append_data)
  try
    set the target_file to the target_file as text
    
set the open_target_file to open for access file target_file with write permission
    
if append_data is false then set eof of the open_target_file to 0
    
write this_data to the open_target_file starting at eof
    
close access the open_target_file
    
return true
  on error error_message
    try
      close access file target_file
    end try
    
return error_message
  end try
end write_to_file

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

2012/06/30 Satimage OSAXを使ってバイナリ書き込みを行う

Satimage OSAXを使ってAppleScriptの命令を拡張し、Satimage OSAXのファイルへのバイナリ書き込み命令を使ってバイナリ書き込みを行うAppleScriptです。

AppleScriptはOSAXと呼ばれるプラグインをインストールすることにより、命令を拡張することができるようになっています。高速なソートや関数演算機能などよりどりみどりの機能がサードパーティのOSAXにより提供されています(多くの場合、フリー配布)。

Satimage OSAXは、世界でもトップクラスの豊富で高レベルの命令を備えるOSAXであり、これをインストールしただけでまるっきり別世界。三角関数だの高速なソートだの、高度な機能が山のように入っています。

OSAXを多用すると、たしかに楽で便利にはなるのですが……自分で作ったものを広く配布するような場合に問題があります(使用はフリーであっても、必ずしも再配布を無制限かつフリーで行えるわけではないので)。

また、Mac OS Xも数年に一度、大規模な環境の変化がありました。Classic Mac OSからの移行、Carbonからの脱却、PowerPCからIntelへの移行、32ビットから64ビットへの移行、新たなセキュリティ機構への対処などなど……簡単に思いつくだけでも(OSのメジャーアップデートに対応するのも大変なのに)、さまざまな試練が発生。

これらの試練を乗り切ったOSAXだけがいまも継続して提供されていますが、乗り切れないものもあったわけです。Mac OS X時代に入ってOSAXへの依存度を(個人的に)減らした理由がここにあります(AppleScript StudioによるGUIベースのアプリ開発、配布をにらんでのことでもあります)。

そのため、いつもギリギリまでOSAXを使わずに標準機能だけでプログラムを書いていますが、バイナリの読み書きなどAppleScriptの標準命令だけではなんともできない用途には、あっさりあきらめてOSAXを用いたほうが得策です。

AppleScript標準の「write」命令を使って0〜255までのバイナリデータをファイル書き込みを行おうとすると、127以上のデータが置き換えられてしまいます(92=0×5Cも変わってしまっています。Thanks!! > dreirossさん)。

スクリプト名:指定ファイルにバイナリで1バイト書き込む
–未遂(これはダメなサンプルです)

set aFileName to choose file name

repeat with i from 0 to 255
  write_to_file_1byte(i, aFileName, true) of me
end repeat

–指定ファイルにバイナリで1バイト書き込む
–追記データ、追記対象ファイル、boolean(trueで追記)
on write_to_file_1byte(oneByteData, target_file, append_data)
  
  
set aClass to (class of oneByteData) as string
  
if aClass is not in {“integer”, “number”, “real”} then return false
  
  
set oneByteDataBin to string id oneByteData
  
  
try
    set target_file to the target_file as text
    
set open_target_file to open for access file target_file with write permission
    
    
if append_data is false then set eof of open_target_file to 0
    
    
write oneByteDataBin as string to open_target_file starting at eof for 1
    
–write oneByteData to open_target_file starting at eof for 1
    
    
close access open_target_file
    
return true
  on error error_message
    try
      close access file target_file
    end try
    
return error_message
  end try
end write_to_file_1byte

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

dump1.png
▲標準命令の「write」で127以上の数値を書き込もうとするとダメ

この問題を解決できるのが、Satimage OSAXの「write binary」命令です。

satimageosax.png

AppleScriptエディタを終了させてSatimage OSAXをインストールすると、すぐにSatimage OSAXの命令が使えるようになります(再起動不要)。一度インストールすれば、何度もインストールする必要はありません(バージョンアップは、新バージョンのOSAXのインストーラの実行によって行います。つまり、自動でアップデートチェックはしてくれません)。

スクリプト名:Satimage OSAXを使ってバイナリ書き込みを行う Sub
set aFile to choose file name with prompt “バイナリファイル書き込みを行うファイルを指定”

repeat with i from 0 to 255
  writeBnary(aFile, i) of me
end repeat

–Caution !! This AppleScript require “Satimage OSAX” from Satimage Software
– http://www.satimage.fr/software/en/downloads/downloads_companion_osaxen.html
on writeBnary(aFile, aData)
  set ref_num to open for access aFile with write permission
  
write binary ref_num with data aData as byte
  
close access ref_num
end writeBnary

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

dump2.png

▲Satimage OSAXを用いて、正しく0〜255までの数値をバイナリ書き込みできた

2012/06/30 8ビットの2進数文字列を10進数に戻す

“1″と”0″で構成された8ビットの2進数文字列を評価して10進数に変換するAppleScriptです。

「エンコーダーを作ったらデコーダーも作れ」(逆もしかり)というのは、もはや常識を通り越して当たり前な話なわけですが、「ちょっとした気の迷い」で作った2進数エンコーダーのおまけにデコーダーを作るのは、さほど行数は長くならないことが分かっていたとしても、けっこう気が滅入ります。

おもえば……作る前に「こんなの誰かが作って公開しているだろう」と考えて、探さなかったところに敗因が……

bin2.png

スクリプト名:8ビットの2進数文字列を10進数に戻す
set aStr to “11110100″
set aNum to binaryDecode(aStr) of me
–> 244

–8ビットの2進数文字列を10進数に戻す
on binaryDecode(aStr)
  –エラーチェック
  
set aLen to length of aStr
  
if aLen is not equal to 8 then return false
  
  
set aNum to 0
  
repeat with i from 7 to 0 by -1
    set aCon to contents of character (8 - i) of aStr
    
    
if aCon = “1″ then
      set aNum to aNum + (2 ^ i)
    end if
    
  end repeat
  
  
return aNum as integer
  
end binaryDecode

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

2012/06/30 0〜255の範囲の10進数を2進数の文字列に変換して返す

10進数の数値を8ビットの2進数文字列に変換して返すAppleScriptです。

ビット演算を行うさいに、別に2進数文字列を経由しないで計算することはできるわけですが、デバッグの都合上どうしても2進数の文字列で見えたほうがよいとの理由で作ってみました。

そもそも最初は、IEEE754の浮動小数点形式の4バイト(32ビット)のデータを作ろうと思いたち、そのためにこのバイナリ文字列エンコーダーとかバイナリ文字列デコーダーとかを作り出して、ついでもあるのでビットシフト演算やローテート演算など……(人間の言葉に近いという意味の)超高級言語のAppleScriptで、CPUのアセンブリコード並みの超低級言語に出てくる演算を実装しているのがシュールです。

bin1.png

スクリプト名:0〜255の範囲の10進数を2進数の文字列に変換して返す
set aNum to 244
set aStr to binaryEncode(aNum) of me
–> "11110100"

–0〜255の範囲の10進数を2進数の文字列に変換して返す
on binaryEncode(aNum)
  –エラーチェック
  
if aNum < 0 or 255 < aNum then return false
  
  
set bitStr to ""
  
  
repeat with i from 7 to 0 by -1
    try
      set aRes to aNum div (2 ^ i)
      
set aNum to aNum mod (aRes * (2 ^ i))
    on error
      set aRes to 0
    end try
    
    
set aRes to aRes as integer
    
set bitStr to bitStr & (aRes as string)
  end repeat
  
  
return bitStr
  
end binaryEncode

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

2012/06/24 FinderのLabelのユーザー環境ごとにカスタマイズした名称を取得

Finderのラベルの各色に対して、ユーザーが付けた名称を取得するAppleScriptです。

たしかに、やろうと思っても普通にはできなかった処理ですが…………それほど、意味ないですよね。

初回掲載したリストに、国際的な慣習的規約に反する「resultによる複数行間の暗示的な値の受け渡し」が含まれていたので、該当箇所を書き換えました。

finder1.png
▲Finderの「環境設定」を呼び出して……

finder2.png
▲「ラベル」で名称をカスタマイズして指定できる。この一覧を取得できる

スクリプト名:FinderのLabelのユーザー環境ごとにカスタマイズした名称を取得(改)
set aList to get_localizedColorLabelStrings() of me
–> {”なし”, “グレイ”, “グリーン”, “ヤンキー”, “ブルー”, “イエロー”, “レッド”, “オレンジ”}

–FinderのLabelのユーザー環境ごとにカスタマイズした名称を取得
–By Yvan KOENIG
on get_localizedColorLabelStrings()
  set colors_loc to {}
  
  
repeat with i from 0 to 7
    copy (my get_color_loc(i)) to end of colors_loc
  end repeat
  
  
set thePlist to (path to preferences from user domain as text) & “com.apple.Labels.plist”
  
tell application “System Events”
    tell contents of property list file thePlist
      
      
repeat with i from 1 to 7
        try
          set aVal to (value of property list item (“Label_Name_” & i))
          
set item (i + 1) of colors_loc to aVal
        end try
      end repeat
      
    end tell
  end tell
  
  
return colors_loc
  
end get_localizedColorLabelStrings

on get_color_loc(num)
  set path2res to “” & (path to library folder from system domain) & “Frameworks:ApplicationServices.framework:Versions:A:Frameworks:HIServices.framework:Versions:A:Resources:”
  
tell application “Finder” to return localized string (“Label_Name_” & num) from table “Labels” in bundle file path2res
end get_color_loc

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

2012/06/20 WWDC2012のビデオが公開に

AppleがWWDC2012の各Sessionのビデオを公開しました。Apple Developpers Connectionメンバーは、iTunesの「iTunes U」からダウンロードできます。AppleScript関連では、

Session 206 - Secure Automation Techniques in OS X(50分14秒)

をSal SoghoianをはじめとするAppleScriptチームが行っています。Mountain LionことOS X 10.8では、セキュリティ向上の仕組みが強化されるため、このセキュリティ向上機能とScriptなどによる自動化の両立をどのように行うか、という具体的な内容が説明されていました。

AppleのDevelopper Programに登録している方は、ぜひ見ておくとよいでしょう。

merlion.png

どうでもいいことですが、ビデオ中でSal SoghoianがMountain Lionのことを「マーライオン」と呼んでいるようにしか聞こえません(画像出典元:Wikipedia)。

2012/06/20 Sandbox対応したiTunes 10.6.3の挙動の変化

iTunes 10.6.3はこれまでにリリースされたiTunesとは若干挙動が変わっていることを確認していました。どこが違うのかといえば、Mac OS X 10.6.8および10.7.4上でASDictionaryを使ってAppleScript用語辞書をHTMLに書き出すことができないという点です。

もともとASDictionaryは、「appscript」ベースのscript開発のために、AppleScript用語辞書を異なる言語(RubyとかPythonとか)のフォーマットでHTML書き出しすることを目的として作成されたものでした。OSやアプリケーションのバージョン間のAppleScript用語辞書差分検出のために使うというのは、本来のASDictionaryの目的とは異なる用途といえます(すごく役立っています)。

asdic.png

appscriptとは、アプリケーションの操作をRubyやPythonなどの言語処理系に提供するためのもので、AppleScriptの枠組みとは異なる仕組みでAppleScriptと同様の機能を他の言語処理系に提供するためのもの。同じ処理を行うにしても「AppleScript上で処理するよりも速い」といった評判がありました。また、AppleScript自体を習得しなくても、RubyやPythonの知識があればアプリケーションのコントロールが行えるという、RubyやPython系開発者にとってのメリットも存在しました。

appscript自体の将来性について多角的に考察・検討した時期もあったのですが、これがApple純正の枠組みではないため、「将来のOSアップデート時に動かなくなる可能性が高い」と考えられたのと、あくまで極地的な動きでありApple内部やアプリ開発者全体に波及するものではない、という結論に。

国内のScripterとの間で議論も行ったのですが、やはり「すべてを置き換えるためのコストが大きすぎる」点が懸念されました。日本国内はともかく、海外ではAppleScriptに慣れ親しんでいるユーザーやソリューションデベロッパーが大量に存在しているため、いまさらゼロから教育を行うための膨大なコストをAppleが支払うことはしないだろうというのが理由の1つ。

また、アプリケーションを外部からコントロールするタイプの一般的なAppleScriptは言うに及ばず、アプリケーション内に埋め込んで使っているAppleScriptや、アプリケーション独自のScript Menu内から呼び出すタイプのAppleScriptなどなど、OS・アプリケーション内のいたるところに存在しているために、それらをすべて移行させるのは無理(コストに見合わない)だろうという話になりました。

実際、appscriptの仕組み自体がCarbon Apple Event Managerという古いOSのAPIを利用したものであったため、Carbon Apple Event ManagerがMac OS X 10.6以降でサポートされないことがAppleによって表明されると、appscriptの開発およびサポートは中止となりました

appscript1.png

先日、「iTunes 10.6.3 changes AppleScript interface?」と題した海外のBBSの投稿があり、appscript経由でiTunes 10.6.3上の選択状態にあるトラックの情報(AppleScriptでいうところのselection)の取得が行えないという話が出ていました(iTunes 10.6.3上のselectionの取得はAppleScriptからは問題なく行えます)。

このケースでは、すでにサポート外になったCarbon Apple Event Managerを呼んでいるappscriptを利用していること自体が問題ですし、そういう問題が発生しても文句を言えた種類のものではないでしょう。

一方で、ASDictionaryがCarbon Apple Event Managerを用いてAppleScript用語辞書にアクセスしているのか、あるいはSandboxの仕組み上、アプリケーションファイルへのアクセスが限定されたためにHTML書き出しが(Mac OS X 10.6および10.7上で)できないのか、そのあたりははっきりとはしませんが……これから登場してくる「Sandbox化されたアプリケーション」の挙動が、ターゲットOS(Mac OS X 10.8, Mountain Lion)上とそれ以前のOS(10.7, 10.6)上で異なってくる可能性があることを意識する必要があることでしょう。

2012/06/16 インターネットのサービスを利用して日本国内の明日の天気予報を取得する

Livedoorの「お天気Webサービス」を呼び出して、日本国内の天気予報を取得するAppleScriptの改良(?)版です。構文確認(コンパイル)および実行には、仏Satimage SoftwareのフリーのOSAX「XMLLib OSAX」を必要とします。

# 「コンパイル」という言葉にだまされてか、AppleScriptのことを「インタプリタ型言語ではない」と勘違いしている人がたまにいますが、AppleScriptは逐次実行型のインタプリタ型言語です(内部で中間コードに置き換えることをコンパイルと呼んでいるだけです)

天気予報を取得して、その対象日付を求めます(最初のバージョンもここまでやっていました)。

問題はこの日付の文字列フォーマットがそのままではAppleScriptのdateオブジェクトに変換できなかったので……Googleで検索したら、あっさり海外(ドイツ?)で見つかりました。得られた文字列をdateオブジェクトに変換して、日付情報を取得。天気予報日付がcurrent dateの翌日になっていることを確認して値を返します。

明確に「明日」の天気予報を求めるように試してみましたが……はたしてどうでしょう?(これ、あんまりテストしていないもので、、、)

→ このバージョンのAPIが廃止になったので、REST APIを呼び出すように変更しています

スクリプト名:インターネットのサービスを利用して日本国内の明日の天気予報を取得する
–東京の明日の天気を求める
set aRec to getTomorrowWeatherForecast(63) of me –東京

–>
(*
{title:”東京都 東京 - 明日の天気”, yohouDate:”Sun, 17 Jun 2012 00:00:00 +0900″, yohouSakuseiDate:”Sat, 16 Jun 2012 17:00:00 +0900″, yohou:”雨のち曇”, descText:”東京地方と伊豆諸島では、明日昼前にかけて竜巻などの激しい突風、急な強い雨、落雷に注意して下さい。また、伊豆諸島では、強風や高波、濃霧による視程障害に注…
[PR]きょうは洗濯できるかな?“}

*)

on getTomorrowWeatherForecast(cityCode)
  set aDate to current date
  
set aDateNum to day of aDate
  
set dList to {“today”, “tomorrow”}
  
  
repeat with i in dList
    set j to contents of i
    
    
set aRes to getWeatherForecast(cityCode, j) of me
    
set yStr1 to yohouDate of aRes
    
set yStr2 to yohouSakuseiDate of aRes
    
    
set yObj1 to parse_RFC2822_date_string(yStr1) of me –予報対象日付
    
set yObj2 to parse_RFC2822_date_string(yStr2) of me –予報作成日付
    
    
set bDate to day of yObj1
    
    
if aDateNum + 1 = bDate then
      return aRes
    end if
  end repeat
  
  
return false
  
end getTomorrowWeatherForecast

–インターネットのサービスを利用して日本国内の天気予報を取得する
on getWeatherForecast(cityCode, relativeDateString)
  
  
set aURL to “http://weather.livedoor.com/forecast/webservice/rest/v1?” –Livedoor Weather Forecast Service
  
set aCity to (“city=” & cityCode as string) & “&”
  
set aDay to “day=” & relativeDateString
  
  
set allURL to aURL & aCity & aDay
  
  
set XMLbody to XMLOpen allURL
  
set the_root to XMLRoot XMLbody
  
  
set res1 to contents of first item of (XMLGetText (XMLXPath the_root with “/lwws/title”))
  
set res2 to contents of first item of (XMLGetText (XMLXPath the_root with “/lwws/forecastdate”))
  
set res3 to contents of first item of (XMLGetText (XMLXPath the_root with “/lwws/publictime”))
  
set res4 to contents of first item of (XMLGetText (XMLXPath the_root with “/lwws/telop”))
  
set res5 to contents of first item of (XMLGetText (XMLXPath the_root with “/lwws/description”))
  
  
set wRec to {title:res1, yohouDate:res2, yohouSakuseiDate:res3, yohou:res4, descText:res5}
  
  
return wRec
  
end getWeatherForecast

–RFC2022形式の日付文字列をdateオブジェクトに
on parse_RFC2822_date_string(ts)
  –引用元:
  
–http://www.j-schell.de/node/121
  
  
– parses a date string using PHP strtotime.
  
– Returns an AppleScript date
  
– Time is in your local time zone
  
–limits:
  
–19. Jan 2038 03:14:07 UTC
  
–13. Dec 1901 20:45:52 UTC
  
  
set php_cmd to “php -r “
  
set php_script to ?
    “$x = @strtotime($argv[1]);
    if ($x === false)
      print \”error\”;
    else
      print (@date ( \”Y-n-j-G-i-s\”, $x ));”
  set php_script to quoted form of php_script
  
set php_arg to quoted form of ts
  
  
set sh_script to php_cmd & php_script & ” “ & php_arg
  
–log sh_script
  
  
set dt to (do shell script sh_script)
  
  
– let us throw an error if parsing went wrong
  
– change the if line if you need something else
  
– return false
  
– may be an alternative if you want to react on problems
  
– without a try … on error block.
  
if dt = “error” then
    error “Handler parse_date_string could not parse string “” & ts & “”” number -30720
  end if
  
set the_date to current date
  
set day of the_date to 1
  
set {year of the_date, month of the_date, day of the_date, hours of the_date, minutes of the_date, seconds of the_date} to every word of dt
  
return the_date
end parse_RFC2822_date_string

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

2012/06/15 2つのフォルダ間のdiffをとって、変更のあったファイルにラベルを付ける

Mac OS Xに標準装備されているアプリケーションのAppleScript用語辞書を書き出したHTMLを、異なるビルド(ないしはバージョン)間で比較して、変更があったファイルにラベルを付けるAppleScriptです。

β版のOSの新しいビルドがデベロッパー向けに公開されると、ひととおりAppleScript用語辞書に変更が加わっていないかどうか、用語辞書の内容をHTMLに書き出すプログラムを使って、HTML同士をdiffによる比較を行い、変更の検出を行っています

当初、Mac OS Xのバージョンが上がると、アプリケーションの機能にも変更が出て、AppleScriptのプログラムの大幅な書き換えを余儀なくされてきました。OSやアプリ側の変更を未然に察知してそれに備えようという努力のすえに、辞書のHTML書き出しの自動化ソリューションが生まれました。そして、さらに比較まで自動化しようとしたのがこのAppleScriptです。

バージョン番号を含めてAppleScript用語辞書をHTML書き出しているため、数字の文字を除外したファイル名の一覧を作成してマッチングを行います。この仕組みでもさすがに「QuickTime Player 7」と「QuickTime Player」の違いをなんとかできなかった(数字を除外すると別のアプリ同士が同じものとして判断されてしまう)ので、事前に手動で「QuickTime Player 7」を「QuickTime Player seven」と置き換えてから処理しています。

yyyeyoyycyayee2012-06-15-10006e.png
▲処理前

yyyeyoyycyayee2012-06-15-10040e.png
▲処理後(変更のあったAppleScript用語辞書に赤いラベルが付いている)

昔は「OSがバージョンアップされると、どこに変更点があるのか分かりにくい」ことが問題でした。それが、いまでは「どこに変更点があるのか、具体的に判断できる状態になりました。さすがに、実際に動かしての不具合までは自動検出できていませんが、手元に数千本のAppleScriptのストックがあるので、そろそろできそうな気もします(Apple自身が行うべき仕事だと思いますが)。

スクリプト名:2つのフォルダ間のdiffをとって、変更のあったファイルにラベルを付ける
script spd
  property aList : {}
  
property aaList : {}
  
property bList : {}
  
property bbList : {}
end script

–古いバージョンのフォルダ
set aFol to choose folder with prompt “Choose older version folder”
set aList of spd to retFileNamesInAFolder(aFol) of me
tell application “Finder”
  set aaList of spd to (every file of aFol) as alias list
end tell

–新しいバージョンのフォルダ
set bFol to choose folder with prompt “Choose newer version folder”
set bList of spd to retFileNamesInAFolder(bFol) of me
tell application “Finder”
  set bbList of spd to (every file of bFol) as alias list
end tell

set newCount to 1

repeat with i in bList of spd
  set j to contents of i
  
  
set oldCount to 1
  
  
repeat with ii in aList of spd
    set jj to contents of ii
    
    
if j is equal to jj then
      
      
set newFile to contents of item newCount of bbList of spd
      
set oldFile to contents of item oldCount of aaList of spd
      
      
set newFilePosix to POSIX path of newFile
      
set oldFilePosix to POSIX path of oldFile
      
      
set sText to “diff “ & quoted form of newFilePosix & ” “ & quoted form of oldFilePosix
      
      
try
        set sRes to do shell script sText
      on error
        –if sRes is not equal to “” then
        
tell application “Finder”
          set label index of newFile to 2 –Red label
        end tell
        
–end if
      end try
      
      
exit repeat
    end if
    
    
set oldCount to oldCount + 1
    
  end repeat
  
set newCount to newCount + 1
  
end repeat

on retFileNamesInAFolder(aFol)
  
  
tell application “Finder”
    set aList to name of every file of aFol
  end tell
  
  
set aaList to {}
  
repeat with i in aList
    set newWord to forceChars(i) of me
    
set the end of aaList to newWord
  end repeat
  
  
return aaList
  
end retFileNamesInAFolder

–与えられた文字列から、アルファベット+記号の文字「以外の」文字を除外して返す
on forceChars(aKeyWord)
  set anList to {“a”, “b”, “c”, “d”, “e”, “f”, “g”, “h”, “i”, “j”, “k”, “l”, “m”, “n”, “o”, “p”, “q”, “r”, “s”, “t”, “u”, “v”, “w”, “x”, “y”, “z”, “.”, “_”, “-”, “+”}
  
set aKeyWord to aKeyWord as Unicode text
  
set aKeyWord to aKeyWord as string
  
set kList to characters of aKeyWord
  
  
set aStr to “”
  
  
repeat with i in kList
    ignoring case
      if i is in anList then
        set aStr to aStr & i as string
      end if
    end ignoring
  end repeat
  
return aStr
end forceChars

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

2012/06/15 Finderで選択中のフォルダ以下の.DS_Storeファイルを削除する

Finderで選択中のフォルダ以下の.DS_Storeファイルを削除するAppleScriptです。

Script Menuに入れて使用しています(↓)。

yyyeyoyycyayee2012-06-15-01853e.png

同様のAppleScriptに、Windowsに渡したときに大丈夫なZipアーカイブを作成するとか、とにかくいろいろスクリプターの皆様が作っておられるわけですが、そのうちのよくあるプログラムのひとつです。

.DS_Storeファイルは、Finder上のアイコンの位置やラベルの色、コメント……はどうだったか覚えていませんが、単なるUNIXではないMac OS XのFinder環境ならではの情報を保存しておく「隠しファイル」です。Macの環境で使っているかぎりは気にならないところですが、他のOSにそのまま持っていくと嫌がられるので、.DS_Storeファイルの削除ソリューションは、星の数ほど存在するわけです。

スクリプト名:Finderで選択中のフォルダ以下のDS_Storeファイルを削除する
tell application “Finder”
  set a to selection
end tell

if a = {} or a = “” then
  display dialog “Finder上で何も選ばれていません…” buttons {“OK”} default button 1 with icon 1
  
return
else if length of a is not equal to 1 then
  display dialog “Finder上で選択するのは1つのフォルダだけにしてください。” buttons {“OK”} default button 1 with icon 1
  
return
end if

set aSel to first item of a
set aSelAlias to aSel as alias

–選択されていたのがフォルダであったかどうかを判定
set aP to (info for aSelAlias)
set aFol to folder of aP
set apFol to package folder of aP

if aFol = true or apFol = true then
  –フォルダかパッケージが渡された場合(通常処理)
  
–とくに何もしないで後続の処理に行かせる
else
  –ファイルを渡した場合
  
display dialog “フォルダを選択した状態で実行してください” buttons {“OK”} default button 1 with icon 0 with title “Selection Item Error”
  
return
end if

set aPOSXpath to quoted form of POSIX path of aSelAlias

set shellText to “find “ & aPOSXpath & ” -name ‘*.DS_Store’ -type f -delete”
try
  do shell script shellText
on error erM
  display dialog erM with title “ERROR” with icon 1 buttons {“OK”} default button 0
end try

display dialog “DS.Storeファイルの削除を実行しました。” buttons {“OK”} default button 1 with icon 1

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

2012/06/13 AppleScript内でperl正規表現を使う

AppleScriptからperlを呼び出して正規表現によるテキスト検索、置換を行うサンプルです。

ごく近しい知り合いからもらったもので、他の人が作ったScriptをラッピングしてあります。

OSAXで正規表現の命令を追加したり、テキストエディタの正規表現の機能を呼び出したりするのもよいのですが、perlなどの他の言語処理系を呼び出した方がシンプルで済むこともあります。

本サンプルは「穴が開くほど使いまくったもの」(本人談)なので、安定度も折り紙付きです。

スクリプト名:AppleScript内でperl正規表現を使う.scpt
set aStr to “xxxx@ezweb.ne.jp”
set aResult to regex_match(“/ezweb/”, aStr) of doPerlKit
log {“aResult = “, aResult}

if aResult is true then
  –set aStr to regex_replace(”/e/A/”, aStr) of me
  
set aStr to regex_replace(“/e/A/g”, aStr) of doPerlKit –gオプションも使える
  
log {“aStr = “, aStr}
end if

——————————————
–AppleScript内でPerl正規表現を使用するためのルーチン群
——————————————
script doPerlKit
  
  
–★targetがregexにマッチするか判定
  
on regex_match(regex, target)
    set command to “$target = q/” & target & “/; if ($target =~ “ & regex & “){ print q/1/; }else{ print q/0/; }” –※引数を使用してperlコマンド生成
    
set str_result to exec_perl(command) of me
    
return evalResult(str_result) of me
  end regex_match
  
  
–★targetをregexで置換
  
on regex_replace(regex, target)
    set command to “$target = q/” & target & “/; $target =~ s” & regex & “; print $target;” –※引数を使用してperlコマンド生成
    
set str_result to exec_perl(command) of me
    
return evalResult(str_result) of me
    
–return str_result
  end regex_replace
  
  
–★commandをperlで実行
  
on exec_perl(command)
    set one_liner to “perl -e ‘” & command & “‘” as Unicode text
    
    
–エラー処理
    
try
      set str_result to do shell script one_liner –※shell実行
    on error
      set str_result to “syntax error : “ & one_liner –perlがエラーを吐いたとき
    end try
    
return str_result
  end exec_perl
  
  
–★結果がtrueかfalseかerrorか判断
  
on evalResult(str_result)
    if str_result is “1″ then
      return true
    else if str_result begins with “syntax error : “ then
      return str_result
    else
      return false
    end if
  end evalResult
  
end script

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

2012/06/13 おかえり(シンプル版)

読者の方(edama2さん)からの投稿です。以前に私がAppleScript Studioで作成して公開していた(る?)、スリープ解除検知&ユーザー通知アプリケーション「おかえり」の簡略版をMac OS X 10.7から作れるようになったAppleScriptエディタベースのAppleScriptObjCで作られました。

yyyeyoyycyaye-2012-06-13-02922.jpeg

yyyeyoyycyaye-2012-06-10-235739.jpeg

投稿していただいてから公開するまでに時間がかかってしまいましたが……実は、AppleScriptエディタベースのASOCのHTML書き出しツールを用意していなかったためで……ようやく、書き出し用のツール(AppleScriptで記述)を準備しました。

——
<edama2さんより>
今日のネタは「おかえり(シンプル版)」です。なかなか更新されない「おかえり」にいらだちを覚え、ついに自分で作り……というのは冗談で、「Cocoa-applescript aplet」の習作として作ってみました。

スリープの復帰の通知を受け取り、半透明のウインドウの表示と音を鳴らすだけです。誕生日とか正月だけの特別なウィンドウはありません。

ウインドウの色と音を変更できるようにしたいところですが、Xcodeを使わずコードだけでウィンドウを作るのは結構面倒だったのとシンプル版ということで省略しました。オリジナルの「おかえり」から「Twentieth Anniversary Macintosh.aiff」だけ使用させていただきました。

最初、同じスプリクト内にカスタムビューのコード(MyView.scpt)を書いていたのですが、初期化の際にエラーが出て難儀しました。どうやら別ファイルにしないと上手く初期化してくれないようです。

作成は10.7.4、テストは10.7.4と10.6.8でしました。ASOC Scriptの新規作成は10.7.4でないとできませんが、編集は書き方によっては10.6.8でもできました。

→ アプレット(編集可能)のダウンロード
</edama2さんより>

スクリプト名:おかえり(シンプル版)
property _sound_name : “Twentieth Anniversary Macintosh”

on run
  #通知の登録
  
tell current application’s NSWorkspace’s sharedWorkspace()
    tell notificationCenter()
      addObserver_selector_name_object_(me, “okaeri:”, “NSWorkspaceScreensDidWakeNotification”, missing value)
    end tell
  end tell
end run

on quit
  current application’s NSNotificationCenter’s defaultCenter()’s removeObserver_(me)
  
continue quit
end quit

#ウィンドウを表示→待機→閉じる
on okaeri_(sender)
  set pool to current application’s NSAutoreleasePool’s new() –>意味があるかよくわからないけどとりあえず。
  
  
copy makeWin() to okaeriWindow
  
  
set filePath to current application’s NSBundle’s mainBundle()’s pathForResource_ofType_(_sound_name, “aiff”)
  
current application’s NSSound’s alloc()’s initWithContentsOfFile_byReference_(filePath, true)’s play()
  
  
delay 5
  
  
closeWin_(okaeriWindow)
  
  
pool’s drain() –release()
end okaeri_

#ウィンドウを作成
on makeWin()
  set aScreen to current application’s NSScreen’s mainScreen()
  
set aFrame to {{0, 0}, {800, 250}}
  
set aBacking to current application’s NSBorderlessWindowMask
  
set aDefer to current application’s NSBackingStoreBuffered
  
  
tell current application’s NSWindow’s alloc()
    tell initWithContentRect_styleMask_backing_defer_screen_(aFrame, aBacking, aDefer, false, aScreen)’s autorelease()
      
      
#カスタムビュー
      
tell current application’s MyView’s alloc()
        tell initWithFrame_(aFrame)
          setNeedsDisplay_(true)
          
set aView to it
        end tell
      end tell
      
      
set {origin:{x:x, y:y}, |size|:{width:w, height:h}} to contentView()’s |bounds|()
      
set titleHeight to 26
      
set y2 to h - titleHeight - (titleHeight / 6)
      
      
#タイトルバー
      
set messageText to “スリープ復帰を検出しました(” & (current date) & “)” as text
      
tell current application’s NSTextView’s alloc()
        tell initWithFrame_({{0, y2}, {w, titleHeight}})
          insertText_(messageText)
          
setAlignment_(current application’s NSCenterTextAlignment)
          
setDrawsBackground_(false)
          
setEditable_(false)
          
setFont_(current application’s NSFont’s titleBarFontOfSize_(13))
          
setSelectable_(false)
          
setTextColor_(current application’s NSColor’s whiteColor())
          
aView’s addSubview_(it)
        end tell
      end tell
      
      
set y3 to h - titleHeight
      
set y3 to h - y3 - (y3 / 6)
      
      
#メッセージビュー
      
set myName to current application’s NSProcessInfo’s processInfo()’s environment()’s valueForKey_(”LOGNAME”) as text
      
set messageText to myName & “さん” & return & “おかえりなさい”
      
tell current application’s NSTextView’s alloc()
        tell initWithFrame_({{0, y3}, {w, y2}})
          insertText_(messageText)
          
setAlignment_(current application’s NSCenterTextAlignment)
          
setDrawsBackground_(false)
          
setEditable_(false)
          
setFont_(current application’s NSFont’s fontWithName_size_(”HiraMinPro-W3″, 72))
          
setSelectable_(false)
          
setTextColor_(current application’s NSColor’s whiteColor())
          
aView’s addSubview_(it)
        end tell
      end tell
      
      
#ウィンドウの設定
      
setBackgroundColor_(current application’s NSColor’s clearColor())
      
setContentView_(aView)
      
setDelegate_(me)
      
setDisplaysWhenScreenProfileChanges_(true)
      
setHasShadow_(true)
      
setIgnoresMouseEvents_(not false)
      
setLevel_((current application’s NSScreenSaverWindowLevel) + 10000)
      
setOpaque_(false)
      
setReleasedWhenClosed_(true)
      
|center|()
      
makeKeyAndOrderFront_(me)
      
      
return it
    end tell
  end tell
end makeWin

#ウィンドウを閉じる
on closeWin_(aWindow)
  tell aWindow
    repeat with n from 10 to 1 by -1
      setAlphaValue_(n / 10)
      
delay 0.02
    end repeat
    
|close|()
  end tell
end closeWin_

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

スクリプト名:MyView
script MyView
  property parent : class “NSView”
  
  
on drawRect_(rect)
    
    
–log my |bounds|()
    
set {origin:{x:x, y:y}, |size|:{width:w, height:h}} to my |bounds|()
    
set titleHeight to 26
    
    
set thePath to current application’s NSBezierPath’s bezierPath()
    
    
#タイトルバー
    
set aFrame to {{0, h - titleHeight}, {w, titleHeight}}
    
set aPath to current application’s NSBezierPath’s bezierPathWithRect_(aFrame)
    
set strartColor to current application’s NSColor’s blackColor()’s colorWithAlphaComponent_(0.4)
    
set endColor to current application’s NSColor’s blackColor()’s colorWithAlphaComponent_(0.8)
    
tell current application’s NSGradient’s alloc()
      tell initWithStartingColor_endingColor_(strartColor, endColor)
        drawInBezierPath_angle_(aPath, 270)
      end tell
    end tell
    
thePath’s appendBezierPath_(aPath)
    
    
#メッセージ
    
set aFrame to {{0, 0}, {w, h - titleHeight}}
    
set aPath to current application’s NSBezierPath’s bezierPathWithRect_(aFrame)
    
set strartColor to current application’s NSColor’s blueColor()’s colorWithAlphaComponent_(0.4)
    
set endColor to current application’s NSColor’s blueColor()’s colorWithAlphaComponent_(0.8)
    
tell current application’s NSGradient’s alloc()
      tell initWithStartingColor_endingColor_(strartColor, endColor)
        drawInBezierPath_angle_(aPath, 270)
      end tell
    end tell
    
thePath’s appendBezierPath_(aPath)
    
  end drawRect_
  
end script

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

スクリプト名:CocoaAppletAppDelegate.scpt

– CocoaAppletAppDelegate.applescript
– Cocoa-AppleScript Applet

– Copyright 2011 {Your Company}. All rights reserved.

– This application delegate emulates the OSA script applet by loading “main.scpt” from the
– “Scripts” folder in the application resources and invoking the traditional run/open/reopen/quit
– handlers in response to Cocoa application delegate methods being called.

– This is provided in source form so that you may customize or replace it if your needs go
– beyond the basic applet handlers.

– Some of these methods must guard against re-entrancy, because invoking the main.scpt
– handler may end up invoking the event handler inherited from the current application,
– which calls the application delegate’s method again.

script CocoaAppletAppDelegate
  property parent : class “NSObject”
  
property mainScript : missing value – the applet’s main.scpt
  
property didOpenFiles : false – true = the application opened documents during startup
  
property isOpeningFiles : false – re-entrancy guard: true = in the process of opening files
  
property isReopening : false – re-entrancy guard: true = in the process of re-opening
  
property isQuitting : false – re-entrancy guard: true = in the process of quitting
  
  
on applicationWillFinishLaunching_(aNotification)
    – Insert code here to initialize your application before any files are opened
    
    
– Emulate an OSA Applet: Load the main script from the Scripts resource folder.
    
try
      set my mainScript to load script (path to resource “main.scpt” in directory “Scripts”)
    on error errMsg number errNum
      – Perhaps this should silently fail if it can’t load the script; that way, a Cocoa applet
      
– can just have Cocoa classes and no main.scpt.
      
display alert “Could not load main.scpt” message errMsg & ” (” & errNum & “)” as critical
    end try
  end applicationWillFinishLaunching_
  
  
on applicationDidFinishLaunching_(aNotification)
    – Insert code here to do startup actions after your application has initialized
    
    
if mainScript is missing value then return
    
    
– Emulate an OSA Applet: Invoke the “run” handler.
    
    
– If we have already opened files during startup, don’t invoke the run handler.
    
if didOpenFiles then return
    
    
try
      tell mainScript to run
    on error errMsg number errNum
      if errNum is not -128 then
        display alert “An error occurred while running” message errMsg & ” (” & errNum & “)” as critical
      end if
    end try
    
    
– TODO: Read the applet’s “stay open” flag and quit if it’s false or unspecified.
    
– For now, all Cocoa Applets stay open and require the run handler to explicitly quit,
    
– which is arguably more correct for a Cocoa application, anyway.
    
(* if not shouldStayOpen then
      quit
    end if *)
  end applicationDidFinishLaunching_
  
  
on applicationShouldHandleReopen_hasVisibleWindows_(sender, flag)
    – Insert code here to perform actions in response to a “reopen” event
    
    
if mainScript is missing value then return true
    
    
– Guard against re-entrancy.
    
if not isReopening then
      set isReopening to true
      
      
– Emulate an OSA Applet: Invoke the “reopen” handler. If there isn’t one, let the application object
      
– handle reopen (this is different from an OSA applet, which would do nothing if there is no handler;
      
– this way, the application will perform the usual “create untitled document” behavior by default).
      
try
        tell mainScript to reopen
        
set isReopening to false
        
        
return false
      on error errMsg number errNum
        if errNum is not -128 then
          display alert “An error occurred while reopening” message errMsg & ” (” & errNum & “)” as critical
        end if
      end try
      
      
set isReopening to false
    end if
    
    
return true
  end applicationShouldHandleReopen_hasVisibleWindows_
  
  
on application_openFiles_(sender, filenames)
    – Insert code here to perform actions in response to an “open documents” event
    
    
– Remember that we opened files, to avoid invoking the “run” handler later.
    
set didOpenFiles to true
    
    
– Guard against re-entrancy.
    
if not isOpeningFiles and mainScript is not missing value then
      set isOpeningFiles to true
      
      
try
        – Convert all the filenames from NSStrings to script strings
        
set theFilenameStrings to {}
        
repeat with eachFile in filenames
          set theFilenameStrings to theFilenameStrings & (eachFile as text)
        end repeat
        
        
tell mainScript to open theFilenameStrings
        
set isOpeningFiles to false
        
        
tell sender to replyToOpenOrPrint_(current application’s NSApplicationDelegateReplySuccess)
      on error errMsg number errNum
        if errNum = -128 then
          tell sender to replyToOpenOrPrint_(current application’s NSApplicationDelegateReplyCancel)
        else
          display alert “An error occurred while opening file(s)” message errMsg & ” (” & errNum & “)” as critical
          
tell sender to replyToOpenOrPrint_(current application’s NSApplicationDelegateReplyFailure)
        end if
      end try
      
      
set isOpeningFiles to false
    else
      tell sender to replyToOpenOrPrint_(current application’s NSApplicationDelegateReplyFailure)
    end if
  end application_openFiles_
  
  
on applicationShouldTerminate_(sender)
    – Insert code here to do any housekeeping before your application quits
    
    
– Guard against re-entrancy.
    
if not isQuitting and mainScript is not missing value then
      set isQuitting to true
      
      
– Emulate an OSA Applet: Invoke the “quit” handler; if the handler returns, it has fully
      
– handled the quit message and we should not quit, otherwise, it calls “continue quit”,
      
– which returns error -10000.
      
try
        tell mainScript to quit
        
set isQuitting to false
        
        
return current application’s NSTerminateCancel
      on error errMsg number errNum
        – -128 means there is no quit handler
        
– -10000 means the handler did “continue quit”
        
if errNum is not -128 and errNum is not -10000 then
          display alert “An error occurred while quitting” message errMsg & ” (” & errNum & “)” as critical
        end if
      end try
      
      
set isQuitting to false
    end if
    
    
return current application’s NSTerminateNow
  end applicationShouldTerminate_
  
end script

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

オリジナルの「おかえり」のコアコードは10行ぐらいで、このサンプルよりもはるかに単純な原理で動いています。
いまから10年近く前にすでに動いていたもので、オリジナルコードはAppleScriptだけで記述。公開版は透明ウィンドウを付けるため(だけ)にAppleScript Studioで開発しました。

「おかえり」のアップデートが止まっていたのは、自分が欲しい機能をてんこ盛りに盛り込んで……画面をInterface Builder上でデザインした時点で「こんなに大量のGUI部品のコードを書くのは大変」なことに気づき……そのまま放置状態に陥ってしまったためでしょう(Piyocastをはじめ、個人的な優先順位の高い自作の未公開アプリがいくつもあるので)。

アプリが自分自身のコード量で自滅した、といえなくもありません。

当時は、Mac AppStoreも存在していませんでしたし、フリーで配布するにはバージョンアップに手がかかりすぎる自作ソフト群にうんざりしていた、ということもあります。

いまだったら、AppleScriptObjCならGUI部品のサポートコードを書くのもそれほど手間ではないので、バージョンアップして公開してみてもよいかもしれません。

2012/06/09 インターネットのサービスを利用して日本国内の天気予報を取得する

Livedoorの「お天気Webサービス」を呼び出して、日本国内の天気予報を取得するAppleScriptです。

AppleScriptで、天気予報を取得してiCalやOutlook(Entourage)のスケジュールを変更したり、メールの文面を変更するなどの処理は……それほど難しくもないので、さっくり書いてみました。

「お天気Webサービス」の内容についてはこちらを詳細な仕様についてはこちらを実際に返ってくるXMLのデータ内容についてはこちらを参照してください。

実行には、仏SATIMAGE SOFTWAREのXMLLib OSAXを必要とします。なんでこれ、Appleがお買い上げしてMac OS X標準装備にしないのか不思議なぐらい有用で便利でお気楽で手放せません。

本ルーチンについての問題は、天気予報が出されるタイミングによって希望日が「今日」なのか「明日」なのかが微妙に変わってくる点で、そのあたりは今後のブラッシュアップが必要、といったレベルです。

スクリプト名:インターネットのサービスを利用して日本国内の天気予報を取得する
–東京の今日の天気を求める
set aRec to getWeatherForecast(63) of me

–>
(*
{title:”東京都 東京 - 今日の天気”, yohouDate:”Fri, 08 Jun 2012 00:00:00 +0900″, yohouSakuseiDate:”Fri, 08 Jun 2012 17:00:00 +0900″, yohou:”晴のち曇”, descText:”伊豆諸島では、強風や高波に注意して下さい。

日本の東に中心を持つ高気圧が、東日本をおおっています。また、四国沖から東シナ海をとおり大陸に前線がのびてい…
[PR]きょうは洗濯できるかな?“}

*)

–インターネットのサービスを利用して日本国内の天気予報を取得する
on getWeatherForecast(cityCode)
  set aURL to “http://weather.livedoor.com/forecast/webservice/rest/v1?” –Livedoor Weather Forecast Service
  
set aCity to (“city=” & cityCode as string) & “&”
  
set aDay to “day=today”
  
  
set allURL to aURL & aCity & aDay
  
  
set XMLbody to XMLOpen allURL
  
set the_root to XMLRoot XMLbody
  
  
set res1 to contents of first item of (XMLGetText (XMLXPath the_root with “/lwws/title”))
  
set res2 to contents of first item of (XMLGetText (XMLXPath the_root with “/lwws/forecastdate”))
  
set res3 to contents of first item of (XMLGetText (XMLXPath the_root with “/lwws/publictime”))
  
set res4 to contents of first item of (XMLGetText (XMLXPath the_root with “/lwws/telop”))
  
set res5 to contents of first item of (XMLGetText (XMLXPath the_root with “/lwws/description”))
  
  
set wRec to {title:res1, yohouDate:res2, yohouSakuseiDate:res3, yohou:res4, descText:res5}
  
  
return wRec
  
end getWeatherForecast

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

2012/06/08 EPSファイルの破損チェック(高速版)

EPSファイルの破損チェックを行うAppleScriptです。

一般的な画像ファイルが破損しているかどうかをAppleScriptで調べるためには、Image Eventsで画像サイズを取得することで、エラー検出が行えます

ただし、EPSはこの「一般的な画像」には入らないので、別の方法を考える必要があります。

真っ先に思い浮かぶのが、Illustratorでオープンしてエラー検出を行う方法。しかし、実際に試してみるとIllustratorではそのようなエラー検出ができません。

QuickLook関連のqlmanageコマンドなどで、プレビュー画像やサムネイル画像を作ってみて、破損チェックを行うという手段も使えそうです。しかし、実際の画面表示を伴ったりするのと、それなりに時間がかかります。さらに、追い討ちをかけるように……QuickLookはMac OS X 10.4上では(もともと実装されていないため)動作しません。

そこで、EPSを別のファイル形式に変換するという手段が考えられました。Mac OS X標準装備の「pstopdf」コマンドを呼び出して、PDF変換時にエラーが出るかどうかをチェックすることは可能です。実際、これはかなりうまく行きました。

ただし、そこかしこにPDFファイル(元のEPSよりファイルサイズが大きくなるケースがほとんど)が作られ、出来るたびに消して回ってもよいのですが……しかし、並列処理ルーチンに突っ込んでみたところ、削除処理で問題が出ました。また、ファイルI/Oが多いのでそれなりに時間(10秒ぐらいとか)がかかる点は解消されていませんでした。

そこで、pstopdfコマンドの出力ファイルを「/dev/null」になるように指定してみたところ、どうせ/dev/nullなので出力のディスクI/Oは発生しないため、1ファイルあたり破損検出を2秒以下で処理できました。ディスク容量が圧迫されないし、わざわざゴミファイルを消す必要もないし、いいことづくめです。

世界中を探し回れば、もっといい方法があるかもしれませんが、とりあえずこの方法が気に入り、ヘビーな用途に使っています。

スクリプト名:EPSファイルの破損チェック(高速版)
set aFile to choose file
set aPOSIX to POSIX path of aFile

set sText to “/usr/bin/pstopdf “ & aPOSIX & ” -o /dev/null”

set erF to true
try
  do shell script sText
on error
  set erF to false
end try

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

2012/06/08 日本語数値表現エンコードされた数値のparseテスト v3

日本語数値表現エンコードされた数値文字列のparseを行うAppleScriptのバグ修正版です。

スクリプト名:日本語数値表現エンコードされた数値のparseテスト v3
property scaleList : {“万”, “億”, “兆”, “京”, “垓”, “丈”, “壌”, “溝”, “砂”, “正”, “載”, “極”, “恒河沙”, “阿僧梢”, “那由他”, “不可思議”, “無量大数”}

set a to “10無量大数9997那由他9297載6866正6832砂1967溝1163壌4317丈7692垓2493京8466兆7286億6441万8111″
set b to parseJapaneseEncodedNumericText(a, scaleList) of me
–> {”1″, “0″, “無量大数”, “9″, “9″, “7″, “那由他”, “2″, “9″, “7″, “載”, “8″, “6″, “6″, “正”, “8″, “3″, “2″, “砂”, “9″, “6″, “7″, “溝”, “1″, “6″, “3″, “壌”, “3″, “1″, “7″, “丈”, “6″, “9″, “2″, “垓”, “4″, “9″, “3″, “京”, “4″, “6″, “6″, “兆”, “2″, “8″, “6″, “億”, “4″, “4″, “1″, “万”, “1″, “1″, “1″}–v2

–> {”1″, “0″, “無量大数”, “9″, “9″, “9″, “7″, “那由他”, “9″, “2″, “9″, “7″, “載”, “6″, “8″, “6″, “6″, “正”, “6″, “8″, “3″, “2″, “砂”, “1″, “9″, “6″, “7″, “溝”, “1″, “1″, “6″, “3″, “壌”, “4″, “3″, “1″, “7″, “丈”, “7″, “6″, “9″, “2″, “垓”, “2″, “4″, “9″, “3″, “京”, “8″, “4″, “6″, “6″, “兆”, “7″, “2″, “8″, “6″, “億”, “6″, “4″, “4″, “1″, “万”, “8″, “1″, “1″, “1″}–v3

–日本語エンコーディングされた数値テキストをparseする
–拾壱などの昔の漢字ベースの数字については、別途、「日本語数値表現文字列プリプロセッサ」にて置換処理すること
–十百千万の各文字がscaleListに入っていないことが動作条件(大丈夫)
on parseJapaneseEncodedNumericText(a, scaleList1)
  –桁識別子のリスト自体をバラバラにする
  
set scaleList2 to {}
  
repeat with i in scaleList1
    set j to contents of i
    
set tmpList to characters of j
    
set scaleList2 to scaleList2 & tmpList
  end repeat
  
  
–パラメータを文字単位で分解して、「桁識別子に入っている文字のリスト」(scaleList2)を照合しつつparseする
  
set aList to characters of a
  
  
set newList to {}
  
  
set hitF to false
  
set tmpBuff to “”
  
  
repeat with i in aList
    
    
set j to contents of i
    
    
–対象文字が日本語数値表現エンコーディングに使われている文字のリスト に入っている場合
    
if j is in scaleList2 then
      
      
if hitF = false then
        –立ち上がり
        
set tmpBuff to j
        
set hitF to true
        
      else if hitF = true then
        –継続状態
        
set tmpBuff to tmpBuff & j
      end if
      
    else
      –対象文字が日本語数値表現エンコーディングに使われている文字のリストに 入っていない場合
      
if hitF = true then
        –日本語数値表現エンコーディングに使われている文字列の末尾を検知した
        
set the end of newList to tmpBuff
        
set the end of newList to j –抜けていた(v3で修正)
        
        
set hitF to false
        
set tmpBuff to “”
        
      else
        –通常の数字などはここで処理
        
set the end of newList to j
        
      end if
      
    end if
  end repeat
  
  
–末尾に日本語数値表現エンコーディング桁文字列が入っていた場合への対処(バッファ出力)
  
if tmpBuff is not equal to “” then
    set the end of newList to tmpBuff
  end if
  
  
return newList
  
end parseJapaneseEncodedNumericText

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

2012/06/06 日本語数値表現エンコードされた数値のparseテスト v2

日本語的数値表現された数値文字列テキスト(「3無量大数」とか「5恒河沙」とか)を数値部分と桁インジケータ日本語文字列に分ける(parseする)AppleScriptです。

以前に作ったものが気に入らなかったので、作り直しました。

ちなみに、最近(Mac OS X 10.6以降)もっぱら日本語のparseが賢くなったという評判の、「words of」でparseすると…………残念な結果に。

# 本ルーチンにはバグが見つかったため、新しいバージョンをご参照ください

スクリプト名:日本語数値表現エンコードされた数値のparseテスト v2
property scaleList : {“万”, “億”, “兆”, “京”, “垓”, “丈”, “壌”, “溝”, “砂”, “正”, “載”, “極”, “恒河沙”, “阿僧梢”, “那由他”, “不可思議”, “無量大数”}

set a to “10無量大数9997那由他9297載6866正6832砂1967溝1163壌4317丈7692垓2493京8466兆7286億6441万8111″
set b to parseJapaneseEncodedNumericText(a, scaleList) of me
–> {”1″, “0″, “無量大数”, “9″, “9″, “7″, “那由他”, “2″, “9″, “7″, “載”, “8″, “6″, “6″, “正”, “8″, “3″, “2″, “砂”, “9″, “6″, “7″, “溝”, “1″, “6″, “3″, “壌”, “3″, “1″, “7″, “丈”, “6″, “9″, “2″, “垓”, “4″, “9″, “3″, “京”, “4″, “6″, “6″, “兆”, “2″, “8″, “6″, “億”, “4″, “4″, “1″, “万”, “1″, “1″, “1″}

set a to “10無量大数”
set b to parseJapaneseEncodedNumericText(a, scaleList) of me
–> {”1″, “0″, “無量大数”}

–日本語エンコーディングされた数値テキストをparseする
–拾壱などの昔の漢字ベースの数字については、別途、「日本語数値表現文字列プリプロセッサ」にて置換処理すること
–十百千万の各文字がscaleListに入っていないことが動作条件(大丈夫)
on parseJapaneseEncodedNumericText(a, scaleList1)
  –桁識別子のリスト自体をバラバラにする
  
set scaleList2 to {}
  
repeat with i in scaleList1
    set j to contents of i
    
set tmpList to characters of j
    
set scaleList2 to scaleList2 & tmpList
  end repeat
  
  
–パラメータを文字単位で分解して、「桁識別子に入っている文字のリスト」(scaleList2)を照合しつつparseする
  
set aList to characters of a
  
  
set newList to {}
  
  
set hitF to false
  
set tmpBuff to “”
  
  
repeat with i in aList
    
    
set j to contents of i
    
    
–対象文字が日本語数値表現エンコーディングに使われている文字のリスト に入っている場合
    
if j is in scaleList2 then
      
      
if hitF = false then
        –立ち上がり
        
set tmpBuff to j
        
set hitF to true
        
      else if hitF = true then
        –継続状態
        
set tmpBuff to tmpBuff & j
      end if
      
    else
      –対象文字が日本語数値表現エンコーディングに使われている文字のリストに 入っていない場合
      
if hitF = true then
        –日本語数値表現エンコーディングに使われている文字列の末尾を検知した
        
set the end of newList to tmpBuff
        
set hitF to false
        
set tmpBuff to “”
        
      else
        –通常の数字などはここで処理
        
set the end of newList to j
        
      end if
      
    end if
  end repeat
  
  
–末尾に日本語数値表現エンコーディング桁文字列が入っていた場合への対処(バッファ出力)
  
if tmpBuff is not equal to “” then
    set the end of newList to tmpBuff
  end if
  
  
return newList
  
end parseJapaneseEncodedNumericText

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

2012/06/06 OmniGraffle 5.4へのアップデートはまだ様子見

stopomni.png

OmniGraffleをAppleScriptからコントロールしてワークフローの自動化を行っている方は、まだ最新版のv5.4にアップデートしないことを強くおすすめします。

OmniGraffle v5.3からv5.4にアップデートしたところ、save命令のフォーマット指定でエラーが出るようになってしまいました。ちなみに、両バージョンのAppleScript用語辞書に違いは見られません。

スクリプト名:OmniGraffle 5.4でsave命令の形式指定がおかしくなった
set outFile to choose file name “Select New Filename”
set outFilePOSIXpath to POSIX path of outFile

tell application “OmniGraffle 5″
  tell current export settings
    set area type to selected graphics
    
set draws background to false
    
set export scale to 1
    
set include border to false
    
set resolution to 1.0
  end tell
  
  
set aDoc to document 1
  
  
save aDoc as “PNG” in POSIX file outFilePOSIXpath
end tell

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

上記のサンプルプログラムは、OmniGraffleのキャンバス上で選択中のオブジェクトを指定ファイル名および指定パスに、PNG形式で書き出しを行うものですが、v5.3で動いていたものがv5.4で動かなくなってしまいました。

error.png

OmniGroupにはバグレポート済みですが、v5.4へのアップデートは問題が解決されるまで様子見のほうがよいでしょう。

個人的には、ものすごく困っています。仕様書の自動更新とか、さまざまなAppleScriptでワークフローを自動化してきたもので。ほんとーに困ります。v5.3に戻したいです。

後日談:

2日ほどたって、OmniGroupのSupport Ninja部隊から報告内容をFileしておいたという報告が来ました。優先順位としてはRetina Mac対応とかOS X 10.8対応とかの方が上になるんでしょうけれど、AppleScriptの命令修正も早急に対応していただきたいところです。

2012/06/04 簡易マクロ展開つきのコードチェック v1

AppleScriptによるコードチェックルーチンに若干の柔軟性を加えたものです。

さまざまなコード(製品コードとか、ユーザーコードとか)をチェックするためのサブルーチンに、限定的ながら数字部に柔軟性を持たせたものです。

本来はコードチェックといえば、きまった桁数の数字だったりアルファベットの文字だったり、そういったものの組み合わせがルールどおりに並んでいるかをチェックするというのが処理内容です。

そんなわけで、数字部分は固定桁で作成したあったのですが、部分的に桁数に柔軟性を持たせてみました。コード中、1ヶ所だけ[]で囲んだ桁数を最大桁とするチェックを行います。

とりあえず、当面はこれで(個人的には)用は足りるのですが、ここからさらに柔軟性を加えようとするとプログラムが数倍複雑になってしまいそうです。

やはり正規表現で文字列チェックを行ったほうが簡単に済みそうで……。

スクリプト名:簡易マクロ展開つきのコードチェック v1
set aCode to “01111Q_p_01″ –チェック対象のコード
set ruleCode to “99999Q_p_[9999]” –コードのルールを外部から供給
set aRes to chkCode(aCode, ruleCode) of me
–> {true, true, true, true, true, true, true}

set aCode to “01111Q_p_01″ –チェック対象のコード
set ruleCode to “[999999]Z_p_01″ –コードのルールを外部から供給
set aRes to chkCode(aCode, ruleCode) of me
–> {true, true, true, true, true, true, true}

–超簡易マクロ展開つきのコードチェック
–[99999]の展開を実装(1箇所のみ)。[99999]の場合には、0〜99999の可変桁チェックを実施
on chkCode(aCode, ruleCode)
  set macroPos1 to offset of “[” in ruleCode
  
set macroPos2 to offset of “]” in ruleCode
  
set ruleLen to length of ruleCode
  
  
if {macroPos1, macroPos2} = {0, 0} then
    set aRes to chkCodeSub(aCode, ruleCode) of me
    
  else if (macroPos1 * macroPos2) is not equal to 0 and (macroPos1 < macroPos2) then
    if macroPos1 > 1 then
      –1文字目以外の場合
      
set baseRule1 to text 1 thru (macroPos1 - 1) of ruleCode
    else
      –1文字目に存在する場合
      
set baseRule1 to “”
    end if
    
    
if macroPos2 is not equal to ruleLen then
      –末尾以外の場合
      
set baseRule2 to text (macroPos2 + 1) thru -1 of ruleCode
    else
      –末尾に存在した場合
      
set baseRule2 to “”
    end if
    
    
set paramLen to macroPos2 - macroPos1 - 1
    
set tmpStr to “9″
    
set hitF to false
    
    
repeat with i from 1 to paramLen
      set tmpRule to baseRule1 & tmpStr & baseRule2
      
set aRes to chkCodeSub(aCode, tmpRule) of me
      
if aRes is not equal to false then
        set hitF to true
        
exit repeat
      end if
      
set tmpStr to tmpStr & “9″
    end repeat
    
    
if hitF = false then return false
    
    
return aRes
    
  end if
end chkCode

–コードのチェックを行う(処理本体)
on chkCodeSub(aCode, ruleCode)
  
  
–set ruleCode to “9999Z99″ –コードのルールを記述しておく–> コードのルール自体も外部から供給するようにしてみた
  
set ruleList to characters of ruleCode
  
  
–コード長のチェック
  
set rLen to length of ruleList
  
set aLen to length of aCode
  
if aLen is not equal to rLen then return false
  
  
–与えられたコードをリストに分解
  
set aList to characters of aCode
  
  
set resList to {}
  
  
repeat with i from 1 to rLen
    
    
set j1 to contents of item i of ruleList
    
set j2 to contents of item i of aList
    
    
set {fromID, toID} to getCharRange(j1) of me
    
set aCharCode to ASCII number of j2
    
    
if (aCharCode fromID) and (aCharCode toID) then
      –ルールに合っている場合には何もしない
      
set the end of resList to true
    else
      set the end of resList to false
    end if
    
  end repeat
  
  
return resList
  
end chkCodeSub

–文字レンジを返す
on getCharRange(a)
  set aCode to ASCII number of a
  
  
if aCode 48 and aCode 57 then
    return {48, aCode} –数字(0〜指定数字まで)
  else if aCode 65 and aCode 90 then
    return {65, aCode} –アルファベット(大文字 A〜指定文字まで)
  else if aCode 97 and aCode 122 then
    return {97, aCode} –アルファベット(大文字 a〜指定文字まで)
  else
    return {aCode, aCode} –その他(ハイフンなどの記号を想定。上記とかぶらない文字)
  end if
end getCharRange

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

2012/06/03 無線LANネットワークを指定して接続する

指定の無線LANネットワークを指定して接続するAppleScriptです。

無線LAN経由でネットワーク接続しているMacをスリープさせておいて、指定時刻にスリープ解除。OSの機能で無線LAN接続が復帰するのが普通ですが、復帰しないケースもないことはありません。とくに、Mac OS Xのメジャーアップデートを行ってしばらくして、マイナーアップデートを経た後でこのような現象に直面することもままあります。

スリープ解除後に無線LANのネットワーク接続が復活していない場合には、あらかじめ記憶していたネットワークにAppleScriptで明示的にネットワーク接続を指定する必要が出てきます。そのために作成しました。

スクリプト名:無線LANネットワークを指定する
set netWorkName to “Extreme net_5G” –ネットワーク名
set netWorkPass to “XXXXXXX” –パスワード
set netWorkENcryption to “WPA2″ –ネットワーク暗号方式

setAirportNetwork(netWorkName, netWorkPass, netWorkENcryption) of me

–指定のWi-Fiネットワークに接続する
on setAirportNetwork(aNetworkName, aPassword, aEncType)
  
  
set v2 to system attribute “sys2″ –> 4
  
if v2 6 then
    set hardWareName to “AirPort” –Mac OS X 10.6
    
set aMesStr to “Current AirPort Network: “
  else if v2 7 then
    set hardWareName to “Wi-Fi” –Mac OS X 10.7
    
set aMesStr to “Current Wi-Fi Network: “
  end if
  
  
set dName to getHardwareDeviceName(hardWareName) of me
  
set sText to “/usr/sbin/networksetup -setairportnetwork “ & dName & ” “ & quoted form of aNetworkName & ” “ & aPassword & ” “ & aEncType
  
  
try
    do shell script sText
  on error errorMessage
    return errorMessage
  end try
  
end setAirportNetwork

–指定ハードウェアポートのデバイス名を取得する
on getHardwareDeviceName(targName)
  set sRes to do shell script “/usr/sbin/networksetup -listallhardwareports”
  
set sList to paragraphs of sRes
  
set s1List to items 2 thru -1 of sList
  
  
set s2List to {}
  
repeat with i in s1List
    set j to contents of i
    
if j is equal to “VLAN Configurations” then
      exit repeat
    end if
    
set the end of s2List to j
  end repeat
  
  
–ネットワークポート関連のレコードを作成
  
set s3List to {}
  
set aLen to length of s2List
  
repeat with i from 1 to aLen by 4
    set a1Item to contents of item i of s2List
    
set a1Item to repChar(a1Item, “Hardware Port: “, “”) of me
    
    
set a2Item to contents of item (i + 1) of s2List
    
set a2Item to repChar(a2Item, “Device: “, “”) of me
    
    
set a3Item to contents of item (i + 2) of s2List
    
set a3Item to repChar(a3Item, “Ethernet Address: “, “”) of me
    
    
set the end of s3List to {hardwarePort:a1Item, device:a2Item, ethernetAddress:a3Item}
  end repeat
  
  
repeat with i in s3List
    set j1 to hardwarePort of i
    
set j2 to device of i
    
if j1 is equal to targName then
      return j2
    end if
  end repeat
  
  
return “”
  
end getHardwareDeviceName

–文字置換ルーチン
on repChar(origText, targStr, repStr)
  set {txdl, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, targStr}
  
set temp to text items of origText
  
set AppleScript’s text item delimiters to repStr
  
set res to temp as text
  
set AppleScript’s text item delimiters to txdl
  
return res
end repChar

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

2012/06/03 無線LANネットワーク名称を取得する v1.1

現在接続中の無線LANネットワークの名称を取得するAppleScriptです。

無線LAN接続中の場合には名称文字列を、未接続の場合にはヌルを返します。

air_port_names.png

▲実行時には「Extreme net」が取得される

スクリプト名:無線LANネットワーク名称を取得する v1.1
set aRes to getAirportNetworkName() of me

–無線LANで接続中のネットワーク名称を取得
on getAirportNetworkName()
  
  
set v2 to system attribute “sys2″ –> 4
  
if v2 6 then
    set hardWareName to “AirPort” –Mac OS X 10.6
    
set aMesStr to “Current AirPort Network: “
  else if v2 7 then
    set hardWareName to “Wi-Fi” –Mac OS X 10.7
    
set aMesStr to “Current Wi-Fi Network: “
  end if
  
  
set dName to getHardwareDeviceName(hardWareName) of me
  
set sText to “/usr/sbin/networksetup -getairportnetwork “ & dName
  
  
set sRes to do shell script sText
  
  
if sRes does not start with “You are not associated with “ then
    set sRes2 to repChar(sRes, aMesStr, “”) of me
  else
    set sRes2 to “”
  end if
  
  
return sRes2
  
end getAirportNetworkName

–指定ハードウェアポートのデバイス名を取得する
on getHardwareDeviceName(targName)
  set sRes to do shell script “/usr/sbin/networksetup -listallhardwareports”
  
set sList to paragraphs of sRes
  
set s1List to items 2 thru -1 of sList
  
  
set s2List to {}
  
repeat with i in s1List
    set j to contents of i
    
if j is equal to “VLAN Configurations” then
      exit repeat
    end if
    
set the end of s2List to j
  end repeat
  
  
–ネットワークポート関連のレコードを作成
  
set s3List to {}
  
set aLen to length of s2List
  
repeat with i from 1 to aLen by 4
    set a1Item to contents of item i of s2List
    
set a1Item to repChar(a1Item, “Hardware Port: “, “”) of me
    
    
set a2Item to contents of item (i + 1) of s2List
    
set a2Item to repChar(a2Item, “Device: “, “”) of me
    
    
set a3Item to contents of item (i + 2) of s2List
    
set a3Item to repChar(a3Item, “Ethernet Address: “, “”) of me
    
    
set the end of s3List to {hardwarePort:a1Item, device:a2Item, ethernetAddress:a3Item}
  end repeat
  
  
repeat with i in s3List
    set j1 to hardwarePort of i
    
set j2 to device of i
    
if j1 is equal to targName then
      return j2
    end if
  end repeat
  
  
return “”
  
end getHardwareDeviceName

–文字置換ルーチン
on repChar(origText, targStr, repStr)
  set {txdl, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, targStr}
  
set temp to text items of origText
  
set AppleScript’s text item delimiters to repStr
  
set res to temp as text
  
set AppleScript’s text item delimiters to txdl
  
return res
end repChar

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

2012/06/03 無線LANの電源のONOFF

Macの無線LANのハードウェアの電源ON/OFFを切り替えるAppleScriptです。

無線LAN(AirPort/AirMac)のハードウェアが存在しているMac上で実行することが条件です。

trueを指定すると無線LANの電源オン、falseを指定すると無線LANの電源オフになります。

airport_on.png
▲無線LAN電源オン

airport_off.png
▲無線LAN電源オフ

スクリプト名:無線LANの電源のONOFF
setAirportPower(true) of me –パワーオン
–setAirportPower(false) of me –パワーオフ

–無線LANの電源のON/OFF
on setAirportPower(aStatus)
  –パラメータのエラーチェック
  
if aStatus is not in {true, false} then return
  
  
set v2 to system attribute “sys2″ –> 4
  
if v2 6 then
    set hardWareName to “AirPort” –Mac OS X 10.6
  else if v2 7 then
    set hardWareName to “Wi-Fi” –Mac OS X 10.7
  end if
  
  
set dName to getHardwareDeviceName(hardWareName) of me
  
if aStatus = true then
    set statStr to “on”
  else
    set statStr to “off”
  end if
  
set sText to “/usr/sbin/networksetup -setairportpower “ & dName & ” “ & statStr
  
  
set sRes to do shell script sText
  
end setAirportPower

–指定ハードウェアポートのデバイス名を取得する
on getHardwareDeviceName(targName)
  set sRes to do shell script “/usr/sbin/networksetup -listallhardwareports”
  
set sList to paragraphs of sRes
  
set s1List to items 2 thru -1 of sList
  
  
set s2List to {}
  
repeat with i in s1List
    set j to contents of i
    
if j is equal to “VLAN Configurations” then
      exit repeat
    end if
    
set the end of s2List to j
  end repeat
  
  
–ネットワークポート関連のレコードを作成
  
set s3List to {}
  
set aLen to length of s2List
  
repeat with i from 1 to aLen by 4
    set a1Item to contents of item i of s2List
    
set a1Item to repChar(a1Item, “Hardware Port: “, “”) of me
    
    
set a2Item to contents of item (i + 1) of s2List
    
set a2Item to repChar(a2Item, “Device: “, “”) of me
    
    
set a3Item to contents of item (i + 2) of s2List
    
set a3Item to repChar(a3Item, “Ethernet Address: “, “”) of me
    
    
set the end of s3List to {hardwarePort:a1Item, device:a2Item, ethernetAddress:a3Item}
  end repeat
  
  
repeat with i in s3List
    set j1 to hardwarePort of i
    
set j2 to device of i
    
if j1 is equal to targName then
      return j2
    end if
  end repeat
  
  
return “”
  
end getHardwareDeviceName

–文字置換ルーチン
on repChar(origText, targStr, repStr)
  set {txdl, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, targStr}
  
set temp to text items of origText
  
set AppleScript’s text item delimiters to repStr
  
set res to temp as text
  
set AppleScript’s text item delimiters to txdl
  
return res
end repChar

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

2012/06/03 指定ハードウェアポートのデバイス名を取得する v1.1

ネットワーク関連の指定ハードウェアポートのデバイス名を取得するAppleScriptです。

指定ハードウェアポートといっても、無線LAN(AirPort……日本国内ではAirMac)のデバイス名称を調べるためだけに作成したものです。それだけではナニなので、汎用的にEhternetやBluetoothなど他のポート名を指定しても対応できるようになっています。

ただし、指定するハードウェアポート名が

Mac OS X 10.6:AirPort
Mac OS X 10.7:Wi-Fi

と、OSバージョンによって異なるので、その点に注意が必要です。

スクリプト名:指定ハードウェアポートのデバイス名を取得する v1.1
set dName to getHardwareDeviceName(“AirPort”) of me –Mac OS X 10.6
–> “en1″ (MacBook Pro Normal Configuration)
–> “en0″ (MacBook Air Normal Configuration)

set dName to getHardwareDeviceName(“Wi-Fi”) of me –Mac OS X 10.7
–> “en1″ (MacBook Pro Normal Configuration)
–> “en0″ (MacBook Air Normal Configuration)

–指定ハードウェアポートのデバイス名を取得する
on getHardwareDeviceName(targName)
  set sRes to do shell script “/usr/sbin/networksetup -listallhardwareports”
  
set sList to paragraphs of sRes
  
set s1List to items 2 thru -1 of sList
  
  
set s2List to {}
  
repeat with i in s1List
    set j to contents of i
    
if j is equal to “VLAN Configurations” then
      exit repeat
    end if
    
set the end of s2List to j
  end repeat
  
  
–ネットワークポート関連のレコードを作成
  
set s3List to {}
  
set aLen to length of s2List
  
repeat with i from 1 to aLen by 4
    set a1Item to contents of item i of s2List
    
set a1Item to repChar(a1Item, “Hardware Port: “, “”) of me
    
    
set a2Item to contents of item (i + 1) of s2List
    
set a2Item to repChar(a2Item, “Device: “, “”) of me
    
    
set a3Item to contents of item (i + 2) of s2List
    
set a3Item to repChar(a3Item, “Ethernet Address: “, “”) of me
    
    
set the end of s3List to {hardwarePort:a1Item, device:a2Item, ethernetAddress:a3Item}
  end repeat
  
  
repeat with i in s3List
    set j1 to hardwarePort of i
    
set j2 to device of i
    
if j1 is equal to targName then
      return j2
    end if
  end repeat
  
  
return “”
  
end getHardwareDeviceName

–文字置換ルーチン
on repChar(origText, targStr, repStr)
  set {txdl, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, targStr}
  
set temp to text items of origText
  
set AppleScript’s text item delimiters to repStr
  
set res to temp as text
  
set AppleScript’s text item delimiters to txdl
  
return res
end repChar

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