Archive for the 'ファイル処理(file)' Category

2017/08/19 PDFの指定ページを削除 v4(複数ページ一括指定)

指定PDF書類のうちの指定ページをまとめて削除するAppleScriptです。

ページ指定にプラスの数値を指定すると絶対ページ数、マイナスの数値を指定するとページ末尾からの相対ページ数として解釈されます。ページ削除前に削除対象のページ数をすべて絶対ページに変換しつつ、重複分を削除し、削除対象ページを降順ソートします。

常識的な範囲内では、PDFからの指定ページ削除は行えるはずです。

ただ、この程度の実装だとすべてのPDFを対象にできないので困ります。Mac App Storeで販売中のアプリ「Double PDF」ではこのあたりの問題を解決したPDF処理ルーチンを仕込んであります。

AppleScript名:PDFの指定ページを削除 v4(複数ページ一括指定)
– Modified 2017-08-19 by Takaaki Naganoya
–Original By Shane Stanley
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “Quartz”
–http://piyocast.com/as/archives/4784

property NSSortDescriptor : a reference to current application’s NSSortDescriptor
property NSArray : a reference to current application’s NSArray
property NSSet : a reference to current application’s NSSet
property |NSURL| : a reference to current application’s |NSURL|
property PDFDocument : a reference to current application’s PDFDocument

set inFile to (choose file of type {“pdf”} with prompt “Choose your PDF files:”)
set targPageList to {1, 3, 5, 7, -1, -2}

set pRes to removeSpecificPagesFromPDF(inFile, targPageList) of me

–指定PDF書類の複数ページの一括削除
on removeSpecificPagesFromPDF(inFileAlias, targPageNumList as list)
  set inNSURL to |NSURL|’s fileURLWithPath:(POSIX path of inFileAlias)
  
set theDoc to PDFDocument’s alloc()’s initWithURL:inNSURL
  
  
–削除対象ページリストをユニーク化して降順ソート(後方から削除)
  
set pRes to theDoc’s pageCount()
  
set t3List to relativeToAbsNumList(targPageNumList, pRes) of me
  
  
repeat with i in t3List
    copy i to targPageNum
    (
theDoc’s removePageAtIndex:(targPageNum - 1))
  end repeat
  
  
–Overwrite Exsiting PDF
  
set aRes to (theDoc’s writeToURL:inNSURL) as boolean
  
  
return aRes
end removeSpecificPagesFromPDF

–絶対ページと相対ページが混在した削除対象ページリストを絶対ページに変換して重複削除して降順ソート
on relativeToAbsNumList(aList, aMax)
  set newList to {}
  
  
repeat with i in aList
    set j to contents of i
    
if i < 0 then
      set j to aMax + j
    end if
    
    
if (j aMax) and (j is not equal to 0) then
      set the end of newList to j
    end if
  end repeat
  
  
set t1List to my uniquify1DList(newList, true)
  
set t2List to my sort1DNumList:t1List ascOrder:false
  
  
return t2List
end relativeToAbsNumList

on absNum(q)
  if q is less than 0 then set q to -q
  
return q
end absNum

–1D/2D Listをユニーク化
on uniquify1DList(theList as list, aBool as boolean)
  set aArray to NSArray’s arrayWithArray:theList
  
set bArray to aArray’s valueForKeyPath:“@distinctUnionOfObjects.self”
  
return bArray as list
end uniquify1DList

–Sort 1-Dimension List(String Number List)
on sort1DNumList:theList ascOrder:aBool
  tell NSSet to set theSet to setWithArray_(theList)
  
tell NSSortDescriptor to set theDescriptor to sortDescriptorWithKey_ascending_(“floatValue”, aBool)
  
set sortedList to theSet’s sortedArrayUsingDescriptors:{theDescriptor}
  
return (sortedList) as list
end sort1DNumList:ascOrder:

★Click Here to Open This Script 

2017/08/19 PDFの指定ページを削除 v3(PDFDocument経由でアクセス)

指定PDF書類のうちの指定ページを削除するAppleScriptです。

以前、PDFKit中の機能のうち指定ページ(PDFPage)を削除するものがPDFPageに見つからなかったので、新規PDFDocumentを作成して元PDFの削除対象「以外の」ページをコピーして上書き保存することで擬似的にページ削除を実現していました

ページ削除機能がないのはおかしいと考え、しつこく調べていたところ….PDFPageではなくPDFDocumetにページ削除の機能が存在することに気づきました。そのため、PDFPage経由で指定のページを削除してみたものです。

skim1.png
▲実行前

skim2.png
▲実行後(7ページ目を削除した)

AppleScript名:PDFの指定ページを削除 v3(PDFDocument経由でアクセス)
– Modified 2017-08-19 by Takaaki Naganoya
–Original By Shane Stanley
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “Quartz”
–http://piyocast.com/as/archives/4781

property |NSURL| : a reference to current application’s |NSURL|
property PDFDocument : a reference to current application’s PDFDocument

set inFile to (choose file of type {“pdf”} with prompt “Choose your PDF files:”)
set targPage to 7

set pRes to removeSpecificPageInPDF(inFile, targPage) of me

on removeSpecificPageInPDF(inFileAlias, targPageNum)
  set inNSURL to |NSURL|’s fileURLWithPath:(POSIX path of inFileAlias)
  
set theDoc to PDFDocument’s alloc()’s initWithURL:inNSURL
  
  
set pRes to theDoc’s pageCount()
  
if absNum(targPageNum) of me > pRes or targPageNum = 0 then
    error “PDF Page Range error. This PDF document has “ & (pRes as string) & ” pages. But you pointed “ & (targPageNum as string) & ” page from your script. “ & return & ” (available abs range :1…” & (pRes as string) & “, relative range: -1…-” & (pRes as string) & “)”
  end if
  
  
–Allow Relative Page Num ( -1 = the last page)
  
if targPageNum 0 then
    set targPageNum to pRes + targPageNum + 1
  end if
  
theDoc’s removePageAtIndex:(targPageNum - 1)
  
  
–Overwrite Exsiting PDF
  
set aRes to (theDoc’s writeToURL:inNSURL) as boolean
  
  
return aRes
end removeSpecificPageInPDF

on absNum(q)
  if q is less than 0 then set q to -q
  
return q
end absNum

★Click Here to Open This Script 

2017/08/08 Metadata Lib 1.0

Spotlightの仕組みを用いてファイル検索を行うAppleScript Libraries「Metadata Lib」(By Shane Stanley)が公開されました。macOS 10.9以降の環境で利用できます。

Metadata Libのアーカイブをダウンロードしたのちに展開して、~/Library/Script Libraries/フォルダに「Metadata Lib.scptd」ファイルを入れればインストールは完了です。

とくにsdefでAppleScript用語辞書が定義されておらず、ソースもすべて読めるようになっています。ただし、各サブルーチンのハンドラの記法はAppleScriptネイティブの、

 someHander(aParamerer)

ではなく、Objective-C風(AppleScriptObjC風)の、

 someHander:aParameter

となっている点に注意が必要です。

内容に特殊なものはないので、「だいたいこんなかんじだよね〜」という軽いライブラリです。いきなり難解な内容にのたうちまわりながら苦しむといったことはまったくありません。今回のリリースはFirst Releaseですが、次あたりでAppleScript用語辞書をつけてきそうな雰囲気はあります。

mdls系コマンド

ファイルのメタデータを調べるにはシェルの「mdls」コマンドを使いますが、それと同じ内容を得られます。ただし、レコード中にオブジェクトを入れて返してくるので、mdfindよりも高速とのことです(Shane本人から念押し)。

use scripting additions
use mdLib : script “Metadata Lib” version “1.0.0″

set theFile to choose file
set theRecord to mdLib’s fetchMetadataFor:theFile

利用するだけれあれば、とくにAppleScriptObjCやCocoaの知識は必要とされません。

mdfind系コマンド

ファイルのメタデータ検索を行うにはシェルの「mdfind」コマンドを使いますが、だいたい同じです。本ライブラリで特徴的なのはNSPredicateで指定するPredicate文を記述して検索条件を指定する点にあります(自分はPredicate文は隠蔽するタチなので)。

また、mdfindよりも高速に検索が行える(Shane本人より念押し)ことに特徴があります。これは、mdfindがPOSIX Pathをテキストで返してくるのでAppleScript側で行単位にparseしつつPOSIX path経由でaliasに変換するような「データ変換」とshell呼び出しのオーバーヘッドの部分を指しているものと思われます(以前、mdfindとCocoa呼び出しで速度比較して、10%ぐらいCocoa呼び出しのほうが高速でした)。

そのため、本ライブラリでこの手のコマンドを利用するにはAppleScriptObjCやCocoaの知識が若干必要です。

もし、極力Cocoaの知識を使わずに本ライブラリによるメタデータ検索を行いたい場合には、あらかじめ検索パターンをFinder上で保存しておけば、searchStringsFromSavedSearch:ハンドラで保存しておいた検索パターンを指定して(Predicate文などを書かずに)、メタデータ検索を行うことも可能です(Shane本人より念押し)。

ひととおりライブラリの中身を見て回った感想は、Metadata検索系の機能だけでなく、ファイル検索系の他の機能も一緒にまとめてみては? というものでした。つまり、個人的にはぜんぜん使っていないFinder Tagとか、よく使っているFinder Labelによる検索とか、NSFileManagerによる再帰検索(Spotlightが効かない状態でも有効)など、バラバラに存在しているものを統合するといいんじゃないかと思えてきました。

どうなんでしょう?

2017/08/02 指定のアプリケーションのURL Schemeを取得する

指定のアプリケーションに設定してあるURL Schemeを取得するAppleScriptです。

指定のアプリケーションバンドル内のInfo.plistにあるCFBundleURLSchemesにアクセスして、カスタムURLプロトコルスキームを取得します。実行にはShane Stanleyの「Bridge Plus」AppleScriptライブラリを~/Library/Script Librariesフォルダにインストールしておくことが必要です。

たとえば、写真.app(Photos.app)であれば「photos://」というカスタムURLプロトコルが定義されており、本Scriptを実行して写真.app(Photos.app)を選択すると、

–> {appName:”Photos”, appBundleID:”com.apple.Photos”, urlScheme:{”photos”}}

という結果が返ってきます。

実際に調べてみると、OSのメジャーアップデート時に予想外のアプリケーションにカスタムURLスキームが新設されていることがあります。そういう調査のために作成したものです。

もちろん、1つのアプリケーションをいちいちchoose fileで選択して調べるとかそういうことではなく、指定フォルダ以下のアプリケーションをすべて取得して、それらのアプリケーションすべてのURL Schemeを調査するScriptのための部品です。手作業で1つ1つ調べるなんて、意味のないことです。

AppleScript名:指定のアプリケーションのURL Schemeを取得する
– Created 2017-07-23 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use BridgePlus : script “BridgePlus”
–http://piyocast.com/as/archives/4759

load framework

set aP to choose file
set aURLrec to getAppURLSchemes(aP) of me
–> {appName:”Photos”, appBundleID:”com.apple.Photos”, urlScheme:{”photos”}}

on getAppURLSchemes(aP)
  set aURL to current application’s |NSURL|’s fileURLWithPath:(POSIX path of aP)
  
set aBundle to current application’s NSBundle’s bundleWithURL:aURL
  
set aDict to aBundle’s infoDictionary()
  
  
set appNameDat to (aDict’s valueForKey:“CFBundleName”) as string
  
set bundleIDat to (aDict’s valueForKey:“CFBundleIdentifier”) as string
  
  
set urlSchemes to (aDict’s valueForKey:“CFBundleURLTypes”)
  
if urlSchemes is not equal to missing value then
    set urlList to urlSchemes’s valueForKey:“CFBundleURLSchemes”
    
set urlListFlat to (current application’s SMSForder’s arrayByFlattening:urlList) as list
  else
    set urlListFlat to {}
  end if
  
  
set aRec to {appName:appNameDat, appBundleID:bundleIDat, urlScheme:urlListFlat}
  
return aRec
end getAppURLSchemes

★Click Here to Open This Script 

2017/07/25 NSImageの垂直、水平反転

指定の画像を読み込んでNSImageにして、垂直反転、水平反転するAppleScriptです。

NSImageそのものを回転させるのはもんのすごく大変そうなので、反転だけしてみました。

piyowolf.png
▲オリジナル画像

flipimagevertically.png
▲垂直方向に反転した画像(flipImageVertically)

flipimagehorizontally.png
▲水平方向に反転した画像(flipImageHorizontally)

回転させるなら元画像よりひとまわり大きなNSImageViewを作ってNSImageを設定し、回転系のmethodでも呼び出して、透過部分を自動トリミングすればいいんじゃないか、などと思っています。

あるいは、NSAffineTransformで90度回転、270度回転の状態を作って、そのターゲットサイズの空白画像の上に重ね合わせるとか。とりあえず、参考にするObjective-CのプログラムをWeb上で探してはみるものの、NSImageそのものを回転させる記述例にはあまりお目にかかりません。

以上はあくまで「Cocoaの機能を直接利用した場合の話」であり、一般的な画像回転はOS標準装備のImageEventsを呼び出して手軽に行えます。

→ ImageEventsで画像回転(時計回りに90度)
→ ImageEventsで画像回転(反時計回りに90度)

AppleScript名:NSImageの垂直、水平反転
– Created 2017-07-25 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
–https://stackoverflow.com/questions/10936590/flip-nsimage-on-both-axes
–http://piyocast.com/as/archives/4748

set aFile to POSIX path of (choose file of type {“public.image”} with prompt “Select an Image”)

set currentImage to current application’s NSImage’s alloc()’s initWithContentsOfFile:aFile
set imgRes to flipImageHorizontally(currentImage) of me
set fRes to retUUIDfilePath(aFile, “png”) of me
set sRes to saveNSImageAtPathAsPNG(imgRes, fRes) of me

–水平方向の画像反転
on flipImageHorizontally(anNSImage)
  set transform to current application’s NSAffineTransform’s transform()
  
set dimList to anNSImage’s |size|()
  
set flipList to {-1.0, 0.0, 0.0, 1.0, dimList’s width, 0.0}
  
set tmpImage to current application’s NSImage’s alloc()’s initWithSize:(dimList)
  
tmpImage’s lockFocus()
  
transform’s setTransformStruct:flipList
  
transform’s concat()
  
anNSImage’s drawAtPoint:(current application’s NSMakePoint(0, 0)) fromRect:(current application’s NSMakeRect(0, 0, dimList’s width, dimList’s height)) operation:(current application’s NSCompositeCopy) fraction:1.0
  
tmpImage’s unlockFocus()
  
return tmpImage
end flipImageHorizontally

–垂直方向の画像反転
on flipImageVertically(anNSImage)
  set transform to current application’s NSAffineTransform’s transform()
  
set dimList to anNSImage’s |size|()
  
set flipList to {1.0, 0.0, 0.0, -1.0, 0.0, dimList’s height}
  
set tmpImage to current application’s NSImage’s alloc()’s initWithSize:(dimList)
  
tmpImage’s lockFocus()
  
transform’s setTransformStruct:flipList
  
transform’s concat()
  
anNSImage’s drawAtPoint:(current application’s NSMakePoint(0, 0)) fromRect:(current application’s NSMakeRect(0, 0, dimList’s width, dimList’s height)) operation:(current application’s NSCompositeCopy) fraction:1.0
  
tmpImage’s unlockFocus()
  
return tmpImage
end flipImageVertically

on retUUIDfilePath(aPath, aEXT)
  set aUUIDstr to (current application’s NSUUID’s UUID()’s UUIDString()) as string
  
set aPath to ((current application’s NSString’s stringWithString:aPath)’s stringByDeletingLastPathComponent()’s stringByAppendingPathComponent:aUUIDstr)’s stringByAppendingPathExtension:aEXT
  
return aPath
end retUUIDfilePath

–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

★Click Here to Open This Script 

2017/06/16 指定PDFの最初のページに大量のスクウェアアノテーションを添付する

指定PDFの最初のページに大量のスクウェアアノテーションを添付するAppleScriptです。

他のGUIアプリケーションを併用せずQuartz Frameworkの機能を利用して、PDFに対するアノテーションの添付を行います。

square_anno1.png

PDFのアノテーションまわりはmacOS 10.13で大幅に変更されているため、本Scriptがそのまま10.13上でも動作することは期待していません。

AppleScript名:指定PDFの最初のページに大量のスクウェアアノテーションを添付する
– Created 2017-06-16 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “Quartz”
use framework “AppKit”
–http://piyocast.com/as/archives/4688

set aHFSPath to (choose file of type {“com.adobe.pdf”} with prompt “Select PDF”)
set aPOSIX to POSIX path of aHFSPath
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 aPage to aPDFdoc’s pageAtIndex:0

set firstPage to (aPDFdoc’s pageAtIndex:0)

–Remove Annotation
my removeAnnotationFromPage:firstPage –Call by Reference

–Get PDF size by Point
set aBounds to aPage’s boundsForBox:(current application’s kPDFDisplayBoxMediaBox)
set aSize to |size| of aBounds

–Add Annotation
repeat with xNum from 30 to ((width of aSize) - 30) by 50
  repeat with yNum from 30 to ((height of aSize) - 30) by 50
    set squAnn to (current application’s PDFAnnotationSquare’s alloc()’s initWithBounds:{origin:{x:xNum, y:yNum}, |size|:{width:40, height:40}})
    (
squAnn’s setValue:(current application’s NSColor’s blueColor()) forAnnotationKey:(current application’s kPDFAnnotationKey_Color))
    (
squAnn’s setValue:(current application’s NSColor’s clearColor()) forAnnotationKey:(current application’s kPDFAnnotationKey_InteriorColor))
    (
firstPage’s addAnnotation:squAnn)
  end repeat
end repeat

–Save It
aPDFdoc’s writeToFile:aPOSIX

–Remove All Annotation from a Page. Call by Reference
on removeAnnotationFromPage:aPage
  set anoList to (aPage’s annotations()) as list
  
repeat with i in anoList
    (aPage’s removeAnnotation:i)
  end repeat
end removeAnnotationFromPage:

★Click Here to Open This Script 

2017/06/03 指定フォルダ中のPure ASのファイルを別フォルダに移動

指定フォルダ中のPure AppleScriptのファイルを別フォルダに移動するAppleScriptです。

最近は(処理速度が速いことや並列実行させやすいことから)なるべくCocoaの機能を呼び出すASOC(AppleScriptObjC)の部品を使うようにしているので、Pure AppleScript(Cocoaの機能を使わないもの)のファイルを整理して別フォルダに移動させておくためのScriptを書いてみました。

任意のAppleScript書類からソースを取得して、ソース中にuse framework “Foundation”の宣言文が入っていないかどうかを確認しています。入っていればASOC、入っていなければPure ASと判定。実行専用のScriptからはソースコードは取得できないので無視していますし、実行形式のアプレットについては最初の段階で対象外にしています。

AppleScript名:指定フォルダ中のPure ASのファイルを別フォルダに移動
– Created 2017-06-03 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “OSAKit”
–http://piyocast.com/as/archives/4673

set tFol to choose folder with prompt “処理対象フォルダを選択”
set sFol to choose folder with prompt “Pure AppleScriptの移動先フォルダを選択”

tell application “Finder”
  tell folder (tFol)
    set sList to (every file whose name ends with “.scpt” or name ends with “.scptd”) as alias list
  end tell
end tell

repeat with i in sList
  set sRes to detectScriptIsPureASorASOC(i) of me
  
if sRes = false then
    tell application “Finder”
      move i to sFol
    end tell
  end if
end repeat

–指定AppleScriptファイルがPure ASかASOCかを判定して返す
on detectScriptIsPureASorASOC(aFile)
  set sText to getASsourceFor(aFile) of me
  
if sText = “” or sText = missing value then return missing value
  
if sText contains “use framework \”Foundation\”" then
    return true –ASOC (AppleScript with Cocoa Framework)
  else
    return false –Pure AppleScript
  end if
end detectScriptIsPureASorASOC

–指定AppleScriptファイルのソースコードを取得する(実行専用Scriptからは取得できない)
on getASsourceFor(anAlias as {alias, string})
  set anHFSpath to anAlias as string
  
set aURL to current application’s |NSURL|’s fileURLWithPath:(POSIX path of anHFSpath)
  
set theScript to current application’s OSAScript’s alloc()’s initWithContentsOfURL:aURL |error|:(missing value)
  
return theScript’s source() as text
end getASsourceFor

★Click Here to Open This Script 

2017/03/15 Spotlightで指定フォルダ以下の指定文字を含むファイル一覧を取得

Cocoaの機能を呼び出すAppleScriptObjCでは、さまざまなCocoaのAPIを呼び出す手法が模索されてきました。その中でもSpotlight検索は「割とまだ決定版の手法が確立していない」ものでありました。

spotlightでタグを指定して検索
http://piyocast.com/as/archives/3731

ASOCでmdfindするじっけん v4(フルパスを返す)
http://piyocast.com/as/archives/4122

などなど、徐々に進化してきて、Shane StanleyのAppleScript Libraries「BridgePlus」にSpotlightの呼び出し命令が実装されたりと、手段が洗練されてきたという経緯があります。

書籍「AppleScript 10大最新技術」にも掲載していますが、その時点のバージョンよりもはるかにこなれた書き方がML上でShane Stanleyから提示されました。いままでよりもはるかに短いので、ちょっと腰を抜かしてしまったほど。しかも、とてもさりげなく、、、

「ああ、こういう書き方でもいいんだ、、、」

と、かなりすごいことになっています。

AppleScript名:Spotlightで指定フォルダ以下の指定文字を含むファイル一覧を取得
– Created 2017-03-15 By Shane Stanley
use AppleScript version “2.4″ – Yosemite (10.10) or later
use framework “Foundation”
use scripting additions
–http://piyocast.com/as/archives/4528

set thePath to POSIX path of (path to desktop) – whatever

–ファイル名で検索
set theKeyword to “スクリーンショット”
set fResList to my searchPath:thePath searchPredicate:“(kMDItemFSName CONTAINS [c]%@)” predicateArgs:{theKeyword}
–>  {”/Users/me/Desktop/2013/03/スクリーンショット 2016-12-15 8.44.28.png”, “/Users/me/Desktop/FromDesktop/samples/list splitted or broken/スクリーンショット 2015-08-31 10.49.30.png”, …… }

–UTI(File Kind)で検索
set theKeyword to “public.png”
set fResList to my searchPath:thePath searchPredicate:“(kMDItemContentType == [c]%@)” predicateArgs:{theKeyword}
–> {”/Users/me/Desktop/2013/03/スクリーンショット 2016-12-15 8.44.28.png”, “/Users/me/Desktop/FromDesktop/IMG_3143_resized.png”, “/Users/me/Desktop/FromDesktop/asoctable.png”….}

–ファイルの内容で検索
set fResList to my searchPath:thePath searchPredicate:“(kMDItemTextContent == [c]%@)” predicateArgs:{“戦場の絆”}
–>  {”/Users/me/Desktop/2013/01/gundam_games_history.txt”, “/Users/me/Desktop/book1_2.0.pdf”}

on searchPath:thePath searchPredicate:predString predicateArgs:argList
  set thePred to current application’s NSPredicate’s predicateWithFormat:predString argumentArray:argList
  
set targetURL to current application’s |NSURL|’s fileURLWithPath:thePath
  
set theQuery to current application’s NSMetadataQuery’s new()
  
  
theQuery’s setPredicate:thePred
  
theQuery’s setSearchScopes:{targetURL}
  
theQuery’s startQuery()
  
  
repeat while theQuery’s isGathering() as boolean
    delay “0.001″ as real
  end repeat
  
theQuery’s stopQuery()
  
  
set theCount to theQuery’s resultCount()
  
set theResults to current application’s NSMutableArray’s array()
  
  
repeat with i from 1 to theCount
    set aResult to (theQuery’s resultAtIndex:(i - 1))
    
set thePath to (aResult’s valueForAttribute:(current application’s NSMetadataItemPathKey))
    (
theResults’s addObject:thePath)
  end repeat
  
  
return (theResults’s sortedArrayUsingSelector:“compare:”) as list
end searchPath:searchPredicate:predicateArgs:

★Click Here to Open This Script 

2017/02/12 GPUImageで輪郭抽出フィルタを実行

オープンソースのフレームワーク「GPUImage」(By Brad Larson)を呼び出して、指定画像に輪郭抽出フィルタを実行して、デスクトップにフィルタ名でPNGに保存するAppleScriptです。

テストにあたっては、GPUImageフレームワークをXcodeでビルドして、~/Library/Frameworksフォルダに入れておいてください。

実際にはもっと凝った処理に使っていますが、その過程でフィルタ名を文字列で間接指定して実行するルーチンが出来てきて、なかなか使い勝手もよくなってきています。

気になる処理速度ですが、MacBook Pro Mid 2012 Core i7 2.6GHzの環境で、

 3,264 × 2,448 pixel、1.2MB → 0.7sec
 3,024 × 4,032 pixel、2.8MB → 1.2sec

ぐらいでした(10回計測時の平均。2回目以降はキャッシュが効いている可能性もあります)。処理中にはこの4Core/8Threadの環境でCPUのロードアベレージが20%ぐらいでまだ余裕があり、AppleScriptで並列処理するともうちょっと速度を稼げるかもしれません。

sample1.png

sample2.png

AppleScript名:GPUImageで輪郭抽出フィルタを実行
– Created 2017-02-12 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “GPUImage” –https://github.com/BradLarson/GPUImage
use framework “AppKit”
–http://piyocast.com/as/archives/4451

set aFile to POSIX path of (choose file of type {“public.image”})
set anImage to current application’s NSImage’s alloc()’s initWithContentsOfFile:aFile
set imgRes to filterWithNSImage(anImage, “GPUImageSobelEdgeDetectionFilter”) of me
set newPath to retUUIDfilePath(aFile, “png”) of me
set sRes to saveNSImageAtPathAsPNG(imgRes, newPath) of me

on retUUIDfilePath(aPath, aEXT)
  set aUUIDstr to (current application’s NSUUID’s UUID()’s UUIDString()) as string
  
set aPath to ((current application’s NSString’s stringWithString:aPath)’s stringByDeletingLastPathComponent()’s stringByAppendingPathComponent:aUUIDstr)’s stringByAppendingPathExtension:aEXT
  
return aPath
end retUUIDfilePath

on filterWithNSImage(aNSImage, filterName as string)
  set aClass to current application’s NSClassFromString(filterName)
  
set aImageFilter to aClass’s alloc()’s init()
  
set aProcImg to (aImageFilter’s imageByFilteringImage:aNSImage)
  
return aProcImg
end filterWithNSImage

–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

★Click Here to Open This Script 

2017/02/09 Application Supportフォルダを求める

Application Supportフォルダを求めるAppleScriptです。

ただ、通常環境(Script Editorとか)を前提としたものではなく(動きますけど)、Xcode上のCocoa-AppleScript Applet内でCodeSignしてApp Sandboxを有効にした環境におけるApplication Supportフォルダを求めるためのものです。

一応、Script Editorや他のAppleScript開発環境でも動きますが、Sandbox環境では返ってくるパスが全然違います。そうした一種の極限環境でも値を取得していろいろやるための実験であります。

AppleScript名:Application Supportフォルダを求める
– Created 2017-02-09 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4450

set fileManager to current application’s NSFileManager’s alloc()’s init()
set bundleID to current application’s NSBundle’s mainBundle()’s bundleIdentifier()
set urlPaths to fileManager’s URLsForDirectory:(current application’s NSApplicationSupportDirectory) inDomains:(current application’s NSUserDomainMask)
set appDirectory to (((urlPaths’s objectAtIndex:0)’s URLByAppendingPathComponent:bundleID isDirectory:true)’s |path|()) as string

–> “/Users/me/Library/Application Support/au.com.myriad-com.ASObjC-Explorer-4″–ASObjC Explorer 4の場合
–> “/Users/me/Library/Application Support/com.apple.ScriptEditor2″–Apple純正のScript Editorの場合

★Click Here to Open This Script 

2017/02/09 choose file,choose folderの始点ディレクトリ指定にPOSIX pathが使える

以前からチラホラ話は聞いていたのですが、choose fileやchoose folderの始点ディレクトリ(コマンド実行時にファイル/フォルダ選択ダイアログに表示されるフォルダ)を指定する「default location」オプション。

この「default location」オプションにPOSIX pathが指定できますよ、というお話です。

pathobjects.png

AppleScript/Cocoa関連の主要なパスオブジェクトはだいたいこの図のようになっていて、最近はCocoaに渡すためにPOSIX pathの登場頻度が高くなっています。ただ、よく出てくるとはいっても、「何かに変換するための一時的な形式」であることが多いようです(個人的に)。

このchoose file/choose folderの始点ディレクトリにPOSIX pathが使えるようになっており、おそらくXcode上で作成するCocoa-AppleScript Applet内で事実上aliasが使えないので、その対策として付加された機能と推測しています(根拠はありません)。ちなみに、同環境でaliasが使いたければ、.scpt形式あるいは.scptd形式のScriptとしてXcodeのプロジェクトに入れて、ASOC側からload scriptしつつ呼び出すような処理になると思います(ライブラリにするやりかたもあるかも)。

AppleScript名:choose fileの始点にPOSIX path
choose file default location “/Users/me/Documents”

★Click Here to Open This Script 

AppleScript名:choose folderの始点にPOSIX path
choose folder default location “/Users/me/Desktop”

★Click Here to Open This Script 

始点ディレクトリはフルパスで指定する必要があり、「~」を併用した記法は使えませんでした。

ちなみに、存在しないPOSIX pathを指定すると、

choose_posix_alias.png

のようなエラーが表示されます。コマンド内部ではaliasに変換しているようです。

この仕様がいつごろから実装されているのかはわかりませんが、おそらくmacOS 10.6以降ではないかと推測されます(AppleScript StudioからAppleScriptObjCへの移行期あたり)。

2017/02/03 2つのパスの相対パスを求める v3

2つのPOSIX pathの相対位置を求めるAppleScriptです。aFileの位置から見た、bFileの相対パス表記を求めます。

MacDown(Mac用のMarkdownエディタ)の作者のuranusjrに「ねー相対パス表記サポートしてよー」とお願いしたところ、単に自分の相対パス表記の書き方が間違っていたことが判明。正しい表記で書いたら現行のMacDown v0.6.4でも問題なく画像への相対パスによるリンク指定ができました。

uranusjrもShane Stanleyも誰も悪くありません。自分が間違っていただけです。

というわけで、相対パス計算ルーチンを修正しておきました。

本ルーチンは、実際にMarkdownで記述した書籍本文中の画像リンク(Dropbox上に設定していた)から、画像をローカルの所定のフォルダにすべてダウンロードし、リンク先をローカル(相対パス指定)に書き換えるAppleScriptで使用しました。

AppleScript名:2つのパスの相対パスを求める v3
– Created 2017-01-28 by Takaaki Naganoya
– Modified 2017-01-30 by Shane Stanley
– Modified 2017-02-03 by Takaaki Naganoya
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4436

set aFile to “/Users/me/Documents/Book1/0900 Command Reference/1000 Command References/1010 tell/1010 tell.md”
set bFile to “/Users/me/Documents/Book1/9999_images/002-640×427.png”

set relativePath to calcRelativePath(aFile, bFile) of me
–>  ”../../../9999_images/002-640×427.png”

on calcRelativePath(aPOSIXfile, bPOSIXfile)
  set aStr to current application’s NSString’s stringWithString:aPOSIXfile
  
set bStr to current application’s NSString’s stringWithString:bPOSIXfile
  
  
set aList to aStr’s pathComponents() as list
  
set bList to bStr’s pathComponents() as list
  
  
set aLen to length of aList
  
set bLen to length of bList
  
  
if aLen bLen then
    copy aLen to aMax
  else
    copy bLen to aMax
  end if
  
  
repeat with i from 1 to aMax
    set aTmp to contents of item i of aList
    
set bTmp to contents of item i of bList
    
    
if aTmp is not equal to bTmp then
      exit repeat
    end if
  end repeat
  
  
set bbList to items i thru -1 of bList
  
set aaItem to (length of aList) - i
  
  
set tmpStr to {}
  
repeat with ii from 1 to aaItem
    set the end of tmpStr to “..”
  end repeat
  
  
set allRes to current application’s NSString’s pathWithComponents:(tmpStr & bbList)
  
return allRes as text
end calcRelativePath

★Click Here to Open This Script 

2017/01/31 DragThing上で選択中のSlotのアイコン画像をデスクトップに書き出す

DragThing上で選択中のSlotのアイコン画像をデスクトップに書き出すAppleScriptです。

ランチャーの老舗、James ThomasonのDragThing(バージョン5.9.17)を愛用しています。macOS標準搭載のDockには最小限のアプリケーションのみ登録しておき、基本的にはDragThingから起動。

dt0.png

dt1.png

さまざまなアプリケーションの紹介を行うKeynote書類を作るために、Finder上で選択しておいたアプリケーションのアイコン画像を書き出すAppleScriptは作ってありました。

dt00_resized.png

その一方で、DragThing上の選択中のアプリケーションのアイコンを書き出すようなものはなかったので、DragThing上で選択→Finderに表示→アイコン書き出しScript実行 と操作していたのですが、あまりに不毛なのでDragThing上から直接書き出せるものを作ってみました。

Dockに大量のアプリケーションを登録し、1個1個が豆粒大になっているユーザーを見かけますが、大量のアプリケーションを登録・管理するのであれば、タブでジャンル分けして管理できるDragThingのほうがおすすめです。

また、DragThingはURLも登録しておけます。DragThingをブックマークとして利用することで、Webブラウザの共通ブックマークとして運用できるため、日常的に複数のWebブラウザを利用している人にとってはたいへん便利でしょう。

dt2_resized.png

dt3.png

macOS標準装備のScript Menuに登録して呼び出しています。

dt4_resized.png

AppleScript名:DragThing上で選択中のSlotのアイコンをデスクトップに書き出し v2
– Created 2017-01-31 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4419

tell application “DragThing”
  –Version 5.9.17で動作確認
  
set aSel to selection
  
if aSel = {} then return
  
  
set bSelected to {}
  
repeat with i in aSel
    set j to contents of i
    
try
      –ここでエラーが出ないということは、Dockに登録したファイルである(URLではない)と仮定
      
set aPath to file location of j
      
      
—選択したSlotの内容がアプリケーションだったらデスクトップにアイコン画像を書き出す
      
set fRes to detectAppFile(aPath) of me
      
if fRes = true then
        writeOutICNS(aPath) of me
      end if
    end try
  end repeat
  
end tell

on detectAppFile(aPath)
  tell application “System Events”
    set fType to file type of aPath
    
return (fType as string = “APPL”)
  end tell
end detectAppFile

–指定ファイルのアイコンをCFBundleIdentifierの名称でtmpにPNGで書き出す
on writeOutICNS(aFile)
  set aPOSIXpath to POSIX path of aFile
  
set anURL to current application’s |NSURL|’s fileURLWithPath:aPOSIXpath
  
  
set myBundle to current application’s NSBundle’s bundleWithURL:anURL
  
set aBundleID to myBundle’s bundleIdentifier() as text
  
set anIconFileName to (myBundle’s objectForInfoDictionaryKey:“CFBundleIconFile”) as string
  
  
–アイコン名には拡張子を省略してもよいので、ない場合には補う
  
if anIconFileName does not end with “.icns” then
    set anIconFileName to anIconFileName & “.icns”
  end if
  
  
set ifonFileFullPath to aPOSIXpath & “Contents/Resources/” & anIconFileName
  
  
set sText to “cp “ & quoted form of ifonFileFullPath & ” ~/Desktop/” & quoted form of (aBundleID & “.icns”)
  
do shell script sText
  
end writeOutICNS

★Click Here to Open This Script 

2016/12/05 アニメーションGIFをフレームごとに画像に分解する

アニメーションGIFを指定すると、指定フォルダ内にフレームごとに個別の連番GIF画像に分解出力するAppleScriptです。

AppleScript名:アニメーションGIFをフレームごとに画像に分解する
– Created 2016-11-29 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
–http://piyocast.com/as/archives/4341

set gifFile to POSIX path of (choose file of type “com.compuserve.gif” with prompt “Select Animation-GIF file”)
set destFol to POSIX path of (choose folder with prompt “Select the folder to save gif’s frames”)

set anImage to current application’s NSImage’s alloc()’s initWithContentsOfFile:gifFile
if anImage is equal to missing value then error “Illegal GIF Image”

set anImgRep to anImage’s representations()’s firstObject()
set framesNum to (anImgRep’s valueForProperty:“NSImageFrameCount”) as integer

repeat with i from 0 to (framesNum - 1)
  (anImgRep’s setProperty:“NSImageCurrentFrame” withValue:i)
  
set aRep to (anImgRep’s representationUsingType:(current application’s NSGIFFileType) |properties|:(missing value))
  (
aRep’s writeToFile:(destFol & (i as string) & “.gif”) atomically:true)
end repeat

★Click Here to Open This Script 

2016/11/05 RTF/RTFDを読み込んでテキスト抽出 v2

リッチテキストフォーマットのファイル(RTF/RTFD)を読み込んでテキストを抽出するAppleScriptの修正版です。

以前に掲載していたバージョンでも動いていたので気づかなかったのですが、オプションの指定に間違いがあり、missing valueと指定すべきところをnullと書いていました(汗)。最初の記述のままでもScript Editor上で動作していたものが、osascriptコマンド経由で実行するとかならずWarning Messageが出る。

 「osascript経由だとWarning Messageが出るのはなぜだー?」
 「それはお前のプログラムが間違っているからだー」

というやりとりをAppleのサポートと行って、Shaneに相談したところ「そこ、間違ってるぞ」という結論に(ーー;;

うん、確かに間違ってた。でも、osascriptコマンドには要らないWarning messageが不意に出力されてくるんで(choose fileコマンド実行時にQuickLookプラグインのWarningとか)、それを止められないのかというのがそもそも指摘したかった事項ではあるのですが、、、

あれ? Warnig Messageの発生源だった「MDQuickLook.qlgenerator」を調査してみたら、これが壊れていたので削除。これに起因するWarning Messageは出なくなりました。

AppleScript名:RTFを読み込んでテキスト抽出 v2
– Created 2016-09-29 by Takaaki Naganoya
– Modified 2016-11-05 by Shane Stanley
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4240
–http://piyocast.com/as/archives/4303

set aFile to choose file of type {“public.rtf”}
set aRes to retTextFromRTF(aFile) of me

on retTextFromRTF(aFile)
  set aFilePath to current application’s NSString’s stringWithString:(POSIX path of aFile)
  
set aData to current application’s NSData’s dataWithContentsOfFile:aFilePath options:0 |error|:(missing value)
  
set theStyledText to current application’s NSMutableAttributedString’s alloc()’s initWithData:aData options:(missing value) documentAttributes:(missing value) |error|:(missing value)
  
  
if theStyledText is not equal to missing value then
    return (theStyledText’s |string|()) as string
  else
    return false –Not RTF file
  end if
end retTextFromRTF

★Click Here to Open This Script 

AppleScript名:RTFDを読み込んでテキスト抽出 v2
– Created 2016-09-29 by Takaaki Naganoya
– Modified 2016-11-05 by Shane Stanley
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4240
–http://piyocast.com/as/archives/4303

set aFile to choose file of type {“com.apple.rtfd”}
set aRes to retTextFromRTFD(aFile) of me

on retTextFromRTFD(aFile)
  set aFilePath to current application’s NSString’s stringWithString:((POSIX path of aFile) & “/TXT.rtf”)
  
set aData to current application’s NSData’s dataWithContentsOfFile:aFilePath options:0 |error|:(missing value)
  
set theStyledText to current application’s NSMutableAttributedString’s alloc()’s initWithData:aData options:(missing value) documentAttributes:(missing value) |error|:(missing value)
  
if theStyledText is not equal to missing value then
    return (theStyledText’s |string|()) as string
  else
    return false –Not RTF file
  end if
end retTextFromRTFD

★Click Here to Open This Script 

2016/10/25 指定ムービーを指定形式に変換する v2

指定のムービーファイルを指定形式に変換するAppleScriptの改良版です。

一晩たったら、旧石器時代から現代までタイムスリップしたぐらいの改良が加わっています(汗)。野蛮な手段でファイル拡張子からUTIを求めていたのが、フレームワーク呼び出し一発で、、、処理速度も大幅に向上しています。

AppleScript名:指定ムービーを指定形式に変換する v2
– Created 2016-10-24 by Shane Stanley
– Modified 2016-10-24 by Takaaki Naganoya
– Modified 2016-10-25 by Shane Stanley
use AppleScript version “2.4″
use framework “Foundation”
use framework “AVFoundation”
use scripting additions
use BridgePlus : script “BridgePlus” –Version 1.3.2以降

load framework
–http://piyocast.com/as/archives/4288

set posixPath to POSIX path of (choose file with prompt “Choose a Movie file:”)
my convertMovieAt:posixPath ToType:“AVAssetExportPresetAppleM4A” withExtension:“m4a” deleteOriginal:false

–指定のムービーを、指定の書き出しプリセットで、指定のファイル形式で、オリジナルファイルを削除するかどうか指定しつつ書き出し
on convertMovieAt:(posixPath as string) ToType:(assetTypeStr as string) withExtension:(aExt as string) deleteOriginal:(deleteFlag as boolean)
  set theURL to current application’s |NSURL|’s fileURLWithPath:posixPath
  
  
set aPreset to current application’s NSString’s stringWithString:assetTypeStr
  
  
– set destination to use same path, different extension
  
set destURL to theURL’s URLByDeletingPathExtension()’s URLByAppendingPathExtension:aExt
  
set theAsset to current application’s AVAsset’s assetWithURL:theURL
  
  
– check asset can be converted
  
set allowedPresets to current application’s AVAssetExportSession’s exportPresetsCompatibleWithAsset:theAsset
  
if (allowedPresets’s containsObject:aPreset) as boolean is false then
    error “Can’t export this file as an .” & aExt & ” file.”
  end if
  
  
– set up export session
  
set fileTypeUTIstr to retFileFormatUTI(aExt) of me –ファイル拡張子からFile Type UTIを求める
  
set theSession to current application’s AVAssetExportSession’s exportSessionWithAsset:theAsset presetName:aPreset
  
theSession’s setOutputFileType:fileTypeUTIstr
  
theSession’s setOutputURL:destURL
  
  
– begin export and poll for completion
  
theSession’s exportAsynchronouslyWithCompletionHandler:(missing value)
  
repeat
    set theStatus to theSession’s status() as integer
    
if theStatus < 3 then
      delay 0.2
    else
      exit repeat
    end if
  end repeat
  
  
– throw error if it failed
  
if theStatus = (current application’s AVAssetExportSessionStatusFailed) as integer then
    error (theSession’s |error|()’s localizedDescription() as text)
  end if
  
  
– delete original if required
  
if deleteFlag then
    current application’s NSFileManager’s defaultManager()’s removeItemAtURL:theURL |error|:(missing value)
  end if
end convertMovieAt:ToType:withExtension:deleteOriginal:

on retFileFormatUTI(aExt as string)
  return (current application’s SMSForder’s UTIForExtension:aExt)
end retFileFormatUTI

★Click Here to Open This Script 

2016/10/25 ムービー系の拡張子からFile Format UTIを取得する v2, v3

ムービー系のファイルの拡張子から、File Format UTIを取得するAppleScriptの改良版です。

Shane Stanleyから指摘があって、

(1)com.apple.quicktime-movieと current application’s AVFileTypeQuickTimeMovieは同じものなので変換する必要はないよ(なんとなく、そうじゃないかとは思ってました ^ー^;;)

(2)BridgePlus v1.3.2に拡張子からUTIを求めるメソッドが用意してあるよ(!!!)

というわけで、(1)を反映させたv2、(2)まで反映させたv3を作成してみましたが、v3にいたってはたったの1行。どこかにもっとスマートな解決策が転がっていると思っていましたが、ここまでスマートになるとは(^ー^;;;

一応、試した範囲ではv1もv2もv3も実行結果は同じです。

AppleScript名:ムービー系の拡張子からFile Format UTIを取得する v2
– Created 2016-10-24 by Takaaki Naganoya
– Modified 2016-10-25 by Takaaki Naganoya
– Modified 2016-10-25 by Shane Stanley
– 2016 Piyomaru Software
use AppleScript version “2.4″
use framework “Foundation”
use framework “AVFoundation”
use framework “AppKit”
use scripting additions
–http://piyocast.com/as/archives/4287

set aRes to retFileFormatUTI(“mov”) of me
–>  (NSString) “com.apple.quicktime-movie”

set aRes to retFileFormatUTI(“mp4″) of me
–>  (NSString) “public.mpeg-4″

set aRes to retFileFormatUTI(“m4v”) of me
–>  (NSString) “com.apple.m4v-video”

set aRes to retFileFormatUTI(“m4a”) of me
–>  (NSString) “com.apple.m4a-audio”

set aRes to retFileFormatUTI(“3gp”) of me
–>  (NSString) “public.3gpp”

set aRes to retFileFormatUTI(“3gp2″) of me
–>  (NSString) “public.3gpp2″

set aRes to retFileFormatUTI(“caf”) of me
–>  (NSString) “com.apple.coreaudio-format”

set aRes to retFileFormatUTI(“wav”) of me
–>  (NSString) “com.microsoft.waveform-audio”

set aRes to retFileFormatUTI(“aif”) of me
–>  (NSString) “public.aifc-audio”

set aRes to retFileFormatUTI(“aifc”) of me
–>  (NSString) “public.aifc-audio”

set aRes to retFileFormatUTI(“amr”) of me
–>  (NSString) “org.3gpp.adaptive-multi-rate-audio”

set aRes to retFileFormatUTI(“mp3″) of me
–>  (NSString) “public.mp3″

set aRes to retFileFormatUTI(“au”) of me
–>  (NSString) “public.au-audio”

set aRes to retFileFormatUTI(“ac3″) of me
–>  (NSString) “public.ac3-audio”

on retFileFormatUTI(aExt)
  set theWorkspace to current application’s NSWorkspace’s sharedWorkspace()
  
set valList to {“com.apple.quicktime-movie”, “public.mpeg-4″, “com.apple.m4v-video”, “com.apple.m4a-audio”, “public.3gpp”, “public.3gpp2″, “com.apple.coreaudio-format”, “com.microsoft.waveform-audio”, “public.aiff-audio”, “public.aifc-audio”, “org.3gpp.adaptive-multi-rate-audio”, “public.mp3″, “public.au-audio”, “public.ac3-audio”}
  
repeat with aUTI in valList
    if (theWorkspace’s filenameExtension:aExt isValidForType:aUTI) as boolean then
      return (current application’s NSString’s stringWithString:aUTI)
    end if
  end repeat
  
error “Invalid Constant String”
end retFileFormatUTI

★Click Here to Open This Script 

AppleScript名:ムービー系の拡張子からFile Format UTIを取得する v3
– Created 2016-10-24 by Takaaki Naganoya
– Modified 2016-10-25 by Shane Stanley
– 2016 Piyomaru Software
use AppleScript version “2.4″
use framework “Foundation”
use framework “AVFoundation”
use scripting additions
use BridgePlus : script “BridgePlus” –Version 1.3.2以降
load framework

–http://piyocast.com/as/archives/4287

set aRes to retFileFormatUTI(“mov”) of me
–>  (NSString) “com.apple.quicktime-movie”

set aRes to retFileFormatUTI(“mp4″) of me
–>  (NSString) “public.mpeg-4″

set aRes to retFileFormatUTI(“m4v”) of me
–>  (NSString) “com.apple.m4v-video”

set aRes to retFileFormatUTI(“m4a”) of me
–>  (NSString) “com.apple.m4a-audio”

set aRes to retFileFormatUTI(“3gp”) of me
–>  (NSString) “public.3gpp”

set aRes to retFileFormatUTI(“3gp2″) of me
–>  (NSString) “public.3gpp2″

set aRes to retFileFormatUTI(“caf”) of me
–>  (NSString) “com.apple.coreaudio-format”

set aRes to retFileFormatUTI(“wav”) of me
–>  (NSString) “com.microsoft.waveform-audio”

set aRes to retFileFormatUTI(“aif”) of me
–>  (NSString) “public.aifc-audio”

set aRes to retFileFormatUTI(“aifc”) of me
–>  (NSString) “public.aifc-audio”

set aRes to retFileFormatUTI(“amr”) of me
–>  (NSString) “org.3gpp.adaptive-multi-rate-audio”

set aRes to retFileFormatUTI(“mp3″) of me
–>  (NSString) “public.mp3″

set aRes to retFileFormatUTI(“au”) of me
–>  (NSString) “public.au-audio”

set aRes to retFileFormatUTI(“ac3″) of me
–>  (NSString) “public.ac3-audio”

on retFileFormatUTI(aExt as string)
  return (current application’s SMSForder’s UTIForExtension:aExt)
end retFileFormatUTI

★Click Here to Open This Script 

2016/10/24 指定ムービーを指定形式に変換する

指定のムービーファイルを指定形式に変換するAppleScriptです。

オリジナルはShane StanleyがAppleScript Users-MLに投稿したものですが、変換(エクスポート)形式が固定で指定されていました(ムービーからオーディオ部のみ書き出し)。

たいへんに有用性が高いものの、エクスポート形式固定のままでは使い勝手がいまひとつだったので、形式を可変指定できるように改修してみました。

エクスポート形式で指定可能なものは、このように一覧を取得できます。この中から選択してください。

本Scriptをそのまま実行すると、指定のムービーファイルから音声部分のみ、同一ファイル名で拡張子を「m4a」にした別ファイルをオリジナルのファイルと同一フォルダ内に書き出します。オリジナルのファイルは消去せずにそのまま残す設定です。

AppleScript名:指定ムービーを指定形式に変換する
– Created 2016-10-24 by Shane Stanley
– Modified 2016-10-24 by Takaaki Naganoya
use AppleScript version “2.4″
use framework “Foundation”
use framework “AVFoundation”
use scripting additions
–http://piyocast.com/as/archives/4286

set posixPath to POSIX path of (choose file with prompt “Choose a Movie file:”)
my convertMovieAt:posixPath ToType:“AVAssetExportPresetAppleM4A” withExtension:“m4a” deleteOriginal:false

–指定のムービーを、指定の書き出しプリセットで、指定のファイル形式で、オリジナルファイルを削除するかどうか指定しつつ書き出し
on convertMovieAt:(posixPath as string) ToType:(assetTypeStr as string) withExtension:(aExt as string) deleteOriginal:(deleteFlag as boolean)
  set theURL to current application’s |NSURL|’s fileURLWithPath:posixPath
  
  
set aPreset to current application’s NSString’s stringWithString:assetTypeStr
  
  
– set destination to use same path, different extension
  
set destURL to theURL’s URLByDeletingPathExtension()’s URLByAppendingPathExtension:aExt
  
set theAsset to current application’s AVAsset’s assetWithURL:theURL
  
  
– check asset can be converted
  
set allowedPresets to current application’s AVAssetExportSession’s exportPresetsCompatibleWithAsset:theAsset
  
if (allowedPresets’s containsObject:aPreset) as boolean is false then
    error “Can’t export this file as an .” & aExt & ” file.”
  end if
  
  
– set up export session
  
set fileTypeUTIstr to retFileFormatUTI(aExt) of me –ファイル拡張子からFile Type UTIを求める
  
set theSession to current application’s AVAssetExportSession’s exportSessionWithAsset:theAsset presetName:aPreset
  
theSession’s setOutputFileType:fileTypeUTIstr
  
theSession’s setOutputURL:destURL
  
  
– begin export and poll for completion
  
theSession’s exportAsynchronouslyWithCompletionHandler:(missing value)
  
repeat
    set theStatus to theSession’s status() as integer
    
if theStatus < 3 then
      delay 0.2
    else
      exit repeat
    end if
  end repeat
  
  
– throw error if it failed
  
if theStatus = (current application’s AVAssetExportSessionStatusFailed) as integer then
    error (theSession’s |error|()’s localizedDescription() as text)
  end if
  
  
– delete original if required
  
if deleteFlag then
    current application’s NSFileManager’s defaultManager()’s removeItemAtURL:theURL |error|:(missing value)
  end if
end convertMovieAt:ToType:withExtension:deleteOriginal:

on retFileFormatUTI(aExt as string)
  set aUTIstr to getUTIfromNameExtension(aExt) of me
  
set keyList to {current application’s AVFileTypeQuickTimeMovie, current application’s AVFileTypeMPEG4, current application’s AVFileTypeAppleM4V, current application’s AVFileTypeAppleM4A, current application’s AVFileType3GPP, current application’s AVFileType3GPP2, current application’s AVFileTypeCoreAudioFormat, current application’s AVFileTypeWAVE, current application’s AVFileTypeAIFF, current application’s AVFileTypeAIFC, current application’s AVFileTypeAMR, current application’s AVFileTypeMPEGLayer3, current application’s AVFileTypeSunAU, current application’s AVFileTypeAC3}
  
set valList to {“com.apple.quicktime-movie”, “public.mpeg-4″, “com.apple.m4v-video”, “com.apple.m4a-audio”, “public.3gpp”, “public.3gpp2″, “com.apple.coreaudio-format”, “com.microsoft.waveform-audio”, “public.aiff-audio”, “public.aifc-audio”, “org.3gpp.adaptive-multi-rate-audio”, “public.mp3″, “public.au-audio”, “public.ac3-audio”}
  
if aUTIstr is not in valList then
    error “Invalid Constant String”
  end if
  
  
set aPos to offsetOf(valList, aUTIstr) of me
  
set cRes to contents of item aPos of keyList
  
return cRes
end retFileFormatUTI

on offsetOf(aList as list, aTarg)
  set aArray to current application’s NSArray’s arrayWithArray:aList
  
set aIndex to (aArray’s indexOfObject:aTarg) as number
  
return (aIndex + 1)
end offsetOf

–ファイル拡張子からUTI文字列を取得する
on getUTIfromNameExtension(anExtStr as string)
  set aTempPath to (POSIX path of (path to temporary items from user domain))
  
set aTempName to (current application’s NSUUID’s UUID()’s UUIDString()) as string
  
set bTempPath to (aTempPath & aTempName & “.” & anExtStr)
  
do shell script “touch “ & quoted form of bTempPath
  
set utiStr to current application’s NSWorkspace’s sharedWorkspace()’s typeOfFile:bTempPath |error|:(missing value)
  
do shell script “rm -f “ & quoted form of bTempPath
  
return utiStr as string
end getUTIfromNameExtension

★Click Here to Open This Script 

2016/10/12 AppleScript自身の「説明」を取得する

実行中のAppleScript自身の「説明」欄に書かれたテキストを取得するAppleScriptです。

scriptcom1.jpg

AppleScript書類がスクリプトバンドル形式になっている場合にかぎられますが、実行中のAppleScript書類自体の「説明」欄に書かれているテキストを取得できます。

「説明」欄についてかる〜くご説明しておきますと、

「説明」欄にはそのAppleScript自体の説明やバージョンアップ履歴を書いておくことが多いようです。好きに使えます。そして、スタイル付きテキストを許容しますし、画像やムービーや音声をペーストしておくことも可能です。Applet書き出しを行い、初期画面を表示させるように設定しておくと、Applet起動時に表示されます。

AppleScriptをスクリプトバンドル形式(.scptd)で保存すると、「説明」欄の内容はバンドル中の、

  /Contents/Resources/description.rtfd

に記録されます。

scriptcom2.jpg

RTFではなくRTFDなので、さらにこのファイル自体がバンドルになっており、

  /Contents/Resources/description.rtfd/TXT.rtf

の中にリッチテキストが入っています。

scriptcom3.jpg

実行中のAppleScriptのパス(path to me)を取得し、そこからスクリプトバンドル中のrtf書類までのパスを組み立て、そこからテキストのみを抽出します。

scriptcmment4.jpg

最初、RTFのつもりでdescription.rtfdにアクセスして、テキストが取得できずに困ってしまいました。

なお、掲載しているAppleScriptのリストにも、文字色が黒なのでわかりにくいですが「説明」欄の内容が入っています(本Blog開設時の8年前から)。こちらは、スクリプトエディタに対してAppleScriptから問い合わせを行って取得しているもので、本Scriptとはアクセス方法が根本的に異なります。

AppleScript名:test script
【コメント】 このScriptの説明文を書いておきますよー
– Created 2016-10-12 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4268

set cRes to retMyComment() of me
–> “このScriptの説明文を書いておきますよー”

on retMyComment()
  set myPath to (path to me) as string
  
set docPath to myPath & “Contents:Resources:description.rtfd:TXT.rtf”
  
set aRes to retTextFromRTF(docPath) of me
  
return aRes
end retMyComment

on retTextFromRTF(aFile)
  set aFilePath to current application’s NSString’s stringWithString:(POSIX path of aFile)
  
set aData to current application’s NSData’s dataWithContentsOfFile:aFilePath options:0 |error|:(missing value)
  
set theStyledText to current application’s NSMutableAttributedString’s alloc()’s initWithData:aData options:(missing value) documentAttributes:(null) |error|:(missing value)
  
if theStyledText is not equal to missing value then
    return (theStyledText’s |string|()) as string
  else
    return false –Not RTF file
  end if
end retTextFromRTF

★Click Here to Open This Script 

2016/09/29 RTFを読み込んでテキスト抽出

指定のRTF(リッチテキスト)ファイルから、プレーンテキストを抽出するAppleScriptです。

→ 本プログラムには間違いがあるので、修正版を利用してください

不等号などの特殊記号について(≠、≥、≤)、スクリプトエディタ以外のサードパーティのAppleScriptエディタ(海外産)でエラーになる場合があるので(ASObjC Explorerとか)、大事をとって特殊記号を使わずに、「is not equal to」などと書くようにしています(あくまで個人的な見解です)。

このために、

tougou_resized.png

のように、Script Assistantで特殊記号類からこれらの英語表記を自動入力しやすいようにしています。

AppleScript名:RTFを読み込んでテキスト抽出
– Created 2016-09-29 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4240

set aFile to choose file of type {“public.rtf”}
set aRes to retTextFromRTF(aFile) of me

on retTextFromRTF(aFile)
  set aFilePath to current application’s NSString’s stringWithString:(POSIX path of aFile)
  
set aData to current application’s NSData’s dataWithContentsOfFile:aFilePath options:0 |error|:(missing value)
  
set theStyledText to current application’s NSMutableAttributedString’s alloc()’s initWithData:aData options:(missing value) documentAttributes:(null) |error|:(missing value)
  
  
if theStyledText is not equal to missing value then
    return (theStyledText’s |string|()) as string
  else
    return false –Not RTF file
  end if
end retTextFromRTF

★Click Here to Open This Script 

2016/07/27 PDFをページごとに分解してJPEGで保存する

指定したPDFをページごとに分解してJPEG画像として保存するAppleScriptです。

書籍のPDFからePubを作ろうとして、さまざまなツールを試して撃沈。日本語のフォントが通らなかったり、オリジナルからかけ離れたレイアウトになったりと散々でした。

ePub版を作るのにそれほど労力を割きたくなかったので、「画像からePub作ろう」と割り切り、PDFをページごとにJPEGに分解することにしました。これを手作業で行っていたのでは日が暮れます。

splittedjpegs.png

そこで、本AppleScriptを作成。ありものを組み合わせたぐらいの作業で完成。さくっとPDFをページごとのJPEG画像に分解できました。

AppleScript名:ASOCでPDFをページごとに分解してJPEGで保存する
– Created 2014-12-26 by Takaaki Naganoya
– Modified 2015-09-26 by Takaaki Naganoya
– Modified 2015-10-01 by Takaaki Naganoya
– Modified 2016-07-27 by Takaaki Naganoya–save each PDF page as jpeg
– 2016 Piyomaru Software
# http://piyocast.com/as/archives/4174

use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “Quartz”
use framework “QuartzCore”
use framework “AppKit”

set aHFSPath to (choose file of type {“com.adobe.pdf”} with prompt “ページごとに分解するPDFを指定してください”)
set aPOSIX to POSIX path of aHFSPath
set aURL to (current application’s |NSURL|’s fileURLWithPath:aPOSIX)

set aPOSIXpath to POSIX path of aHFSPath —書き出し先パスをPOSIX pathで用意しておく(あとで加工)

set aPDFdoc to current application’s PDFDocument’s alloc()’s initWithURL:aURL
set pCount to aPDFdoc’s pageCount()

set compFactor to 1.0 – 0.0 = max jpeg compression, 1.0 = none

–PDFをページごとに分割してJPEGでファイル書き出し
repeat with i from 0 to (pCount - 1)
  set thisPage to (aPDFdoc’s pageAtIndex:(i))
  
set thisDoc to (current application’s NSImage’s alloc()’s initWithData:(thisPage’s dataRepresentation()))
  
if thisDoc = missing value then error “Error in getting imagerep from PDF in page:” & (i as string)
  
  
set theData to thisDoc’s TIFFRepresentation()
  
set newRep to (current application’s NSBitmapImageRep’s imageRepWithData:theData)
  
set targData to (newRep’s representationUsingType:(current application’s NSJPEGFileType) |properties|:{NSImageCompressionFactor:compFactor, NSImageProgressive:false})
  
  
set outPath to addString_beforeExtensionIn_addingExtension_(“_” & (i + 1) as string, aPOSIXpath, “jpg”)
  
  (
targData’s writeToFile:outPath atomically:true) –書き出し
end repeat

–ファイルパス(POSIX path)に対して、文字列(枝番)を追加。任意の拡張子を追加
on addString:extraString beforeExtensionIn:aPath addingExtension:aExt
  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:aExt
  
return newPath as string
end addString:beforeExtensionIn:addingExtension:

★Click Here to Open This Script 

2016/06/18 指定フォルダ以下にあるMacDownとPages書類をソートしてPDFに書き出す

指定フォルダ以下にあるMacDownで記述したMarkdown書類と、Pages書類をすべての階層からピックアップしてファイル名でソートして、すべてデスクトップにPDFで書き出すAppleScriptです。

コンパイル(構文確認)および実行に際しては、Shane StanleyのScript Library「Bridge Plus」をインストールしておく必要があります。また、GUI Scriptingを利用しているため「システム環境設定」>「セキュリティとプライバシー」>「プライバシー」>「アクセシビリティ」でスクリプトエディタ(アプレットとして実行する場合にはアプレットそのもの)を登録して許可しておく必要があります。

「技術書典」に出す電子ブックのフォーマットがギリギリまで決まらず、しかも縦長のスクロールさせるタイプのものにできないかとあがいていたのですが、結局iPadあたりで読むことを考慮するとiPadのリーダーの仕様にしたがう必要があります。

……あれ?(^ー^; 結局、ページめくりは発生するし、一般的な本と同じような体裁になってしまいますよ → フォーマットがPDFになりました。

Markdown書類とPages書類が混在しているフォルダ構造のトップ階層のフォルダを指定すると、Markdown書類とPages書類をピックアップし、ファイル名でそれらをソートし、順次PDFに書き出すAppleScriptを書いてみました(必要は発明のマザー!)。

book1.png

ただ、MacDownには「書類をPDFに書き出す」という機能がAppleScript側に公開されていません(T_T)。

macdown_dict.png

ないものを「ないない」と嘆いても仕方がないので、さっさとGUI Scriptingで強制的にメニュー操作することにしました。

macdown_gui.png

で、どこに? どこに保存させるのでしょう??

大丈夫! そんなときには、保存ダイアログで幾つかのフォルダに強制的に移動させるキーボードショートカットが存在しており、Command-Dは「カレントディレクトリをデスクトップに移動させる」=「保存先をデスクトップにする」働きをします。

このため、保存先を操作しづらい(不可能とはいいませんけれども)GUI Scriptingにおいて保存先を指定することが、デスクトップフォルダについては可能になっています。

Pagesの方はひじょうに素直に(GUI Scriptingなんて使わずに)PDF書き出しが可能です。

そんなわけで、時間に追い詰められながらもなんとか大量のデータ処理を行っているのでありました。書き出した大量のPDFもAppleScriptでさくっと連結できるので、非常にいい感じです。あとは、本が完成すれば、、、、

AppleScript名:指定フォルダ以下にあるMDとPagesをソートしてPDFに書き出す
– Created 2016-06-17 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use BridgePlus : script “BridgePlus”
–use spotLight : script “spotlightLib”

property searchRes : {}

load framework

set origPath to POSIX path of (choose folder with prompt “Markdown/Pages ファイルの入っているフォルダを選択”)

set aResList to (spotlightSearch(origPath, “kMDItemKind == ’Markdown’ || kMDItemKind == ’Pages 一般書類’”) of me) as list –Caution! this parameter is *localized*

–フルパスとファイル名のペアの2D Listを作成
set newList to {}
repeat with i in aResList
  set j to contents of i
  
set aStr to (current application’s NSString’s stringWithString:j)
  
set aFileName to aStr’s lastPathComponent()
  
set the end of newList to {aStr, aFileName}
end repeat

–番号順にソート
set sortIndexes to {1} –Key Item id: begin from 0, Sort by filename
set sortOrders to {true}
set sortTypes to {“compare:”}
set resList to (current application’s SMSForder’s subarraysIn:(newList) sortedByIndexes:sortIndexes ascending:sortOrders sortTypes:sortTypes |error|:(missing value)) as list
if resList = {} then return –No Result

–ソートした順番にMarkdownファイル/Pages書類ファイルをオープンしてデスクトップにPDF生成してクローズ
repeat with i in newList
  copy i to {fullPath, aFileName}
  
  
set apFile to (POSIX file (fullPath as string))
  
set anAlias to apFile as alias
  
set aFileName to aFileName as string
  
  
if aFileName ends with “.md” then
    exportFromMacDown(anAlias) of me –Markdown
  else if aFileName ends with “.pages” then
    exportFromPages(anAlias) of me –Pages
  end if
end repeat

–指定のPagesファイル(alias)をデスクトップ上にPDFで書き出し
on exportFromPages(anAlias)
  tell application “Finder”
    set aName to name of anAlias
  end tell
  
  
set dtPath to (path to desktop) as string
  
set outPath to dtPath & aName & “.pdf”
  
  
tell application “Pages”
    close every document without saving
    
open anAlias
    
export document 1 to file outPath as PDF with properties {image quality:Best}
    
close every document without saving
  end tell
end exportFromPages

–指定のMacDownファイル(alias)をデスクトップ上にPDFで書き出し
on exportFromMacDown(anAlias)
  tell application “MacDown”
    open {anAlias}
  end tell
  
  
tell current application
    delay 1 –ここの時間待ちが少ないと画像抜けが発生?
  end tell
  
macDownForceSave() of me
  
  
tell application “MacDown”
    close every document without saving
  end tell
end exportFromMacDown

–注意!! ここで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

–Spotlight Libの内容を引っ張り出してきた
on spotlightSearch(origPOSIXpath, aCondition)
  
  
set searchRes to {} –initialize
  
  
initiateSearchForFullPath(aCondition, origPOSIXpath) –Predicate & Scope Directory
  
  
–Waiting for the result
  
repeat while searchRes = {}
    current application’s NSThread’s sleepForTimeInterval:(“0.001″ as real) –delay 0.001
  end repeat
  
  
set anObj to searchRes’s firstObject() –Pick up the first one for test
  
if anObj = missing value then return {} –No Result
  
  
–set anAttrList to anObj’s attributes() –”mdls” attributes
  
–>  (NSArray) {”kMDItemContentTypeTree”, “kMDItemContentType”, “kMDItemPhysicalSize”, …}
  
  
set resArray to {}
  
repeat with anItem in my searchRes
    set j to contents of anItem
    
set aPath to (j’s valueForAttribute:“kMDItemPath”) as string
    
set the end of resArray to aPath
  end repeat
  
  
return resArray
end spotlightSearch

on initiateSearchForFullPath(aQueryStrings, origPath)
  
  
set aSearch to current application’s NSMetadataQuery’s alloc()’s init()
  
  
current application’s NSNotificationCenter’s defaultCenter()’s addObserver:(me) selector:“queryDidUpdate:” |name|:(current application’s NSMetadataQueryDidUpdateNotification) object:aSearch
  
current application’s NSNotificationCenter’s defaultCenter()’s addObserver:(me) selector:“initalGatherComplete:” |name|:(current application’s NSMetadataQueryDidFinishGatheringNotification) object:aSearch
  
  
set aPredicate to current application’s NSPredicate’s predicateWithFormat:aQueryStrings
  
aSearch’s setPredicate:aPredicate
  
  
set aScope to current application’s NSArray’s arrayWithObjects:{origPath}
  
aSearch’s setSearchScopes:aScope
  
  
set sortKeys to current application’s NSSortDescriptor’s sortDescriptorWithKey:“kMDItemFSName” ascending:true
  
aSearch’s setSortDescriptors:(current application’s NSArray’s arrayWithObject:sortKeys)
  
  
aSearch’s startQuery()
  
end initiateSearchForFullPath

on queryDidUpdate:sender
  –  
end queryDidUpdate:

on initalGatherComplete:sender
  set anObject to sender’s object
  
anObject’s stopQuery()
  
current application’s NSNotificationCenter’s defaultCenter()’s removeObserver:me |name|:(current application’s NSMetadataQueryDidUpdateNotification) object:anObject
  
current application’s NSNotificationCenter’s defaultCenter()’s removeObserver:me |name|:(current application’s NSMetadataQueryDidFinishGatheringNotification) object:anObject
  
set my searchRes to anObject’s results()
end initalGatherComplete:

★Click Here to Open This Script 

2016/06/17 ASOCでmdfindするじっけん v4(フルパスを返す)

Spotlightの機能をCocoa経由で呼び出してmdfindコマンドのクエリーと検索対象フォルダをPOSIX pathで与えると、条件に合致するファイルのPOSIX pathをリストに入れて返してくるAppleScriptです。

以前に掲載したバージョンを実際に使おうとしたら、激しく間違っていることを発見。なんで気がつかなかったんでしょう。いえ、なんでこんな忙しいときに気づいてしまうんでしょう。

AppleScript名:ASOCでmdfindするじっけん v4(フルパスを返す)
– Created 2016-06-17 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

property searchRes : {}

set origPath to POSIX path of (choose folder)
set aList to spotlightSearch(origPath, “kMDItemContentType == ’net.daringfireball.markdown’”) of me

on spotlightSearch(origPath, aMDfindParam)
  
  
set my searchRes to {} –initialize
  
initiateSearchForFullPath(aMDfindParam, origPath) –Predicate & Scope Directory
  
  
–Waiting for the result
  
repeat while my searchRes = {}
    delay 0.01
  end repeat
  
  
set anObj to my searchRes’s firstObject() –Pick up the first one for test
  
if anObj = missing value then return {} –No Result
  
  
set resArray to {}
  
repeat with anItem in my searchRes
    set j to contents of anItem
    
set aPath to (j’s valueForAttribute:“kMDItemPath”) as string
    
set the end of resArray to aPath
  end repeat
  
  
return resArray
  
end spotlightSearch

on initiateSearchForFullPath(aQueryStrings, origPath)
  
  
set aSearch to current application’s NSMetadataQuery’s alloc()’s init()
  
  
current application’s NSNotificationCenter’s defaultCenter()’s addObserver:(me) selector:“queryDidUpdate:” |name|:(current application’s NSMetadataQueryDidUpdateNotification) object:aSearch
  
current application’s NSNotificationCenter’s defaultCenter()’s addObserver:(me) selector:“initalGatherComplete:” |name|:(current application’s NSMetadataQueryDidFinishGatheringNotification) object:aSearch
  
  
set aPredicate to current application’s NSPredicate’s predicateWithFormat:aQueryStrings
  
aSearch’s setPredicate:aPredicate
  
  
set aScope to current application’s NSArray’s arrayWithObjects:{origPath}
  
aSearch’s setSearchScopes:aScope
  
  
set sortKeys to current application’s NSSortDescriptor’s sortDescriptorWithKey:“kMDItemFSName” ascending:true
  
aSearch’s setSortDescriptors:(current application’s NSArray’s arrayWithObject:sortKeys)
  
  
aSearch’s startQuery()
  
end initiateSearchForFullPath

on queryDidUpdate:sender
  log sender
  
–> (NSConcreteNotification) NSConcreteNotification 0×7fa618450820 {name = NSMetadataQueryDidFinishGatheringNotification; object = }
end queryDidUpdate:

on initalGatherComplete:sender
  set anObject to sender’s object
  
anObject’s stopQuery()
  
current application’s NSNotificationCenter’s defaultCenter()’s removeObserver:me |name|:(current application’s NSMetadataQueryDidUpdateNotification) object:anObject
  
current application’s NSNotificationCenter’s defaultCenter()’s removeObserver:me |name|:(current application’s NSMetadataQueryDidFinishGatheringNotification) object:anObject
  
  
set my searchRes to anObject’s results()
end initalGatherComplete:

★Click Here to Open This Script 

2016/02/19 ASOC上でのファイルパスの変換

AppleScriptObjC(以下、ASOC)上での各種パス形式の変換サンプルのAppleScriptです。

OS X 10.10以降ですべての作成/ランタイム環境でASOCの機能をサポートしたことにより、Pure AppleScript(Cocoa呼び出しなし)とASOC(Cocoa呼び出しあり)を分けること自体が無意味になったため、積極的にCocoaの機能を利用していこうということになりました。

ASOCは、「データを設定する機能はあるが、取得するための機能がない」といったAppleScriptの世界の直交性の低さをユーザー側で解消できる環境になりました。

・・・たとえば、AppleScript標準ではプリンター名を指定して印刷する機能はあっても、標準で出力可能なプリンター名一覧を取得する機能が存在していませんでした(shell script呼び出しCocoaの機能呼び出しで解決)。

また、AppleScript対応機能が不十分かつ不完全なアプリケーション(Calendar.appなど)の機能をアテにしないでFramework経由でデータにアクセスするといった解決方法も見られるようになってきました。

そんなわけで、Pure AppleScriptの世界と不可分になってきたASOCですが、在来型のPure AppleScriptよりも扱うパス情報の「型」が増えました。これらのパス情報を適切に扱い、かつ相互変換する必要性が増えてきたわけです。

以下に、現在ASOC上で扱っているパス情報のかずかずをご紹介します。


 Alias:AppleScript Nativeのパス形式。最もメジャーなもの。フォルダ階層は「:」で区切る。ドライブ名が最上位に位置付けられる。ファイル参照的なもので、いったん変数に入れて保持すると、名前が変わろうがパスが変わろうが同じファイル/フォルダを追跡する。実体が存在しないパス文字列をAliasに変換するとエラーになる

 File: Aliasとは別のAppleScript Nativeのパス形式。追跡機能はない。各種アプリケーションのAppleScript用語辞書にfileと書いてあっても実際にはaliasのことがほとんど(例外もいくつかある)。フォルダ階層は「:」で区切る。ドライブ名が最上位に位置付けられる。実体がないパス文字列をFileに変換可能

 POSIX path:Pure AppleScript/ASOC共通で使う。最近利用頻度が著しく上がった形式。一部のアプリケーションや、shell commandを扱うときに使う。Cocoaで一般的に扱うのはコレ。フォルダ階層は「/」で区切る。root(/)が最上位に位置付けられる。基本的に単なる文字列なので追跡機能はない。Pure AppleScriptではクォート処理(quoted form of)する必要があるものの、ASOCでCocoaのAPIに渡す場合には不要。

 POSIX file:AppleScript Nativeのパス形式。位置付けがめんどくさい。POSIX pathの文字列から生成したFileで、追跡機能はない。POSIX pathをAliasに変換する際にいったん経由する中間形式という認識。個人的には、極力、深入りしないようにしている

 URL:Cocoaで画像のオープンを行うときに使う。画像についていえばオープン時にはURL、保存時にはPOSIX pathを指定するのがとっても不思議。「file://」のプロトコルヘッダーが先頭につく。Alphabet+Numeric以外の文字はURLエンコードされる。。フォルダ階層は「/」で区切る。root(/)が最上位に位置付けられる。追跡機能はない

Pure AppleScriptではパス情報を基本的にAliasで扱います。一部の例外的なアプリケーションでPOSIX pathを要求されたりしますが基本的にはAliasです。

distiller.png
▲例外的に処理対象のファイルにPOSIX pathを要求する、AdobeのAcrobat Distiller。しかもpathにquoted form ofでクォート処理するとダメ。ダメな実装の見本

このあたり、各アプリケーションがどのようなパス情報を期待しているかは、各アプリケーションの用語辞書に書いてあります(書いてあっても実際に試すという作業が必要)。

複数のパス情報形式を扱うことが初心者に混乱を招くことがあるようですが、なんのことはないCocoaでもPOSIX pathとURLなどの複数のパス形式を扱っているため、複数のパス形式を処理ないし変換する必要があるのは、仕方のないことのようです。

なお、本サンプルはScript Editor上での記述・実行を念頭に置いたものであり、Xcode上でASOCを記述したときにまったく同様に動く保証のあるものではありません。Xcode上では極力Cocoaのデータ形式に変換するか文字列で保持するのがセオリーです。

AppleScript名:ファイルパスの変換(Alias→POSIX path→NSURL→POSIX path→file→Alias)
– Created 2016-02-19 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

–Get Alias (AppleScript native file path format)
set anAlias to choose file
–>  alias “Macintosh HD:Users:me:Documents:……”

–Get POSIX path from Alias
set aPOSIX to POSIX path of anAlias
–>  ”/Users/me/Documents/……”

–Get NSURL from POSIX path
set aURL to current application’s |NSURL|’s fileURLWithPath:aPOSIX
–>  (NSURL) file:///Users/me/Documents/………%83%88%EF%BC%92.scptd/

–Get NSURL string
set bPath to aURL’s absoluteString()
–>  (NSString) “file:///Users/me/Documents/A….9C%EF%BC%89.scptd/”

–Get file path (POSIX path) NSString
set cPath to aURL’s |path|()
–>  (NSString) “/Users/me/Documents/……scptd”

–Get POSIX file path string from NSString
set dPath to cPath as string
–>  ”/Users/me/Documents/……..scptd”

–Get file from POSIX path
set aFile to POSIX file dPath
–>  file “Macintosh HD:Users:me:Documents:….scptd”

–Get Alias from file
set bAlias to aFile as alias
–>  alias “Macintosh HD:Users:me:Documents:….scptd”

★Click Here to Open This Script 

2016/02/16 FBEncryptorで文字列の暗号化、復号化(ASOC版)

xcatsanさんが公開されている「AES128暗号化ライブラリ FBEncryptor」を少々書き変えて(ARC対応&フレームワーク化。単なる作業レベル)作ったFBEncryptorKitを呼び出して文字列の暗号化、復号化を行うAppleScriptです。

以前にXcode上のAppleScriptObjCでこれを呼び出すものを書いてみましたが、通常のScript Editorで利用できるようにした方が応用が効くため、Cocoa Frameworkとして別途ビルドしてみました。

OS X 10.10以降用にビルドしたバイナリを用意しましたので、試したい方は(自己責任で)~/Library/Frameworksフォルダに入れて呼び出してください。

–> Download Binary

AppleScript名:FBEncryptorで文字列の暗号化、復号化
– Created 2016-02-16 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “FBEncryptorKit” –https://github.com/dev5tec/FBEncryptor

set aStr to “ABCDEFあいうえお
かきくけこGHIJKLMN”

set aKey to “piyomaru”

–Encryption
set aEnc to current application’s FBEncryptorAES’s encryptBase64String:aStr keyString:aKey separateLines:true
–>  (NSString) “N0/E5FB97DY+qOFtfKK9CCsAMKznyej94Ons1lC90V/9vMJIaBw5R+mbaxaTm711″

–Decription
set aDec to current application’s FBEncryptorAES’s decryptBase64String:aEnc keyString:aKey
(*
(NSString) “ABCDEFあいうえお
かきくけこGHIJKLMN”
*)

★Click Here to Open This Script 

2015/12/22 2フォルダ間のファイル内容比較

Cocoaの機能を用いて、2つのフォルダ内のファイルの内容比較を行うAppleScriptです。

folders.png

複数バージョンのAppleScriptで、処理結果がきちんと同じかどうか比較したいケースがあります。そこで手作業で比較・・・していたのでは意味がありません。

たまたま仕事でCSVを書き出すAppleScriptをバージョンアップしていて、前バージョンの処理結果ととくに変化がないことを検証するために、

 。殴侫ルダ間のファイル名一覧に変更がないこと
 同一ファイル名のファイルで内容が同一であること

をチェックする必要がありました。Pure AppleScriptで書こうとすると、けっこうめんどくさい処理です(書いたことがあるような気がしますが、書き捨てしてしまったのかも)。

Cocoaの機能を使って書くとどうなるのか? 調べてみてあまりに簡潔に書けるので、「本当にこれでいいの?」と、わざと2フォルダ間でファイル数を変えてみたり、同名でまったく内容の違うファイルを入れてみたりしましたが、きちんと検出してくれました。

2フォルダにそれぞれ1050個のCSVファイルを入れた状態で、MacBook Pro Retina 2012で(SSD上で)実行すると比較に1秒かかりません。HDD上で比較を行うとそれなりに時間はかかりますが、Mac mini 2014(Core i5 2.6GHz)上で3秒程度でした。

AppleScript名:2フォルダ間の内容比較
– Created 2015-12-22 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aFol to (choose folder with prompt "Select Folder A")
set bFol to (choose folder with prompt "Select Folder B")

set aPath to POSIX path of aFol
set bPath to POSIX path of bFol

set aFM to current application’s NSFileManager’s defaultManager()
set aRes to (aFM’s contentsEqualAtPath:aPath andPath:bPath) as boolean

★Click Here to Open This Script 

2015/10/29 指定フォルダ内のフォルダのみを取得する

Cocoaの機能を用いて、指定フォルダ以下のフォルダだけを取得するAppleScriptです。

こちらも、US AppleのAppleScript Users MLにShane Stanleyが投稿したものです。ただ、まっとうに処理しているので・・・実行にはそれなりに時間がかかります。Spotlightの機能を用いて取得した方がはるかに高速です。

フォルダだけを抽出するのであればSpotlightを用いることになるでしょうけれど、この用途「以外」で何か別の用途で活用できる雰囲気がしています。

AppleScript名:ASOCで指定フォルダ内のフォルダのみを取得する
– Created 2015-10-13 by Shane Stanley
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set thePath to POSIX path of (choose folder)
set fListRes to my getFoldersIn:thePath
–>  {file "Macintosh HD:Users:me:Pictures:2014カレンダー表紙?", file "Macintosh HD:Users:me:Pictures:ASBook", file "Macintosh HD:Users:me:Pictures:ASBook:AS_beginner", file "Macintosh HD:Users:me:Pictures:Camera Roll", file "Macintosh HD:Users:me:Pictures:DESIGN GARDEN PROJECT", ….

on getFoldersIn:posixPath
  script spd
    property allItems : {}
  end script
  
  
set allItems of spd to {}
  
  
– make URL
  
set theNSURL to current application’s |NSURL|’s fileURLWithPath:posixPath
  
  
– make file manager
  
set theNSFileManager to current application’s NSFileManager’s new()
  
  
– get URL enumerator
  
set theNSFileEnumerator to theNSFileManager’s enumeratorAtURL:theNSURL includingPropertiesForKeys:{current application’s NSURLIsDirectoryKey, current application’s NSURLIsPackageKey} options:((current application’s NSDirectoryEnumerationSkipsPackageDescendants) + (current application’s NSDirectoryEnumerationSkipsHiddenFiles as integer)) errorHandler:(missing value)
  
  
– get all items from enumerator
  
set (allItems of spd) to theNSFileEnumerator’s allObjects()
  
set theFolders to {} – to store folders
  
  
– loop through
  
repeat with i from 1 to count of (allItems of spd)
    – is it a directory?
    
set {theResult, isDirectory} to ((item i of (allItems of spd))’s getResourceValue:(reference) forKey:(current application’s NSURLIsDirectoryKey) |error|:(missing value))
    
if isDirectory as boolean then
      set {theResult, isPackage} to ((item i of (allItems of spd))’s getResourceValue:(reference) forKey:(current application’s NSURLIsPackageKey) |error|:(missing value))
      
      
– is it not a package?
      
if not isPackage as boolean then
        set end of theFolders to (item i of (allItems of spd))’s |path|() as «class furl»
      end if
    end if
  end repeat
  
  
return theFolders
end getFoldersIn:

★Click Here to Open This Script 

2015/10/26 ASOCによるファイルの移動

Cocoaの機能を用いてファイルを移動(move)するじっけんです。

Pure AppleScriptであればFinder経由でmove… to …with replacingで強制移動。do shell script経由でmvしてもいいですし、それほど大変な内容ではない「ファイルの移動」。

これを、Cocoaの機能(NSFileManager)経由で書いて、共有フォルダの内容を(処理後に)処理終了フォルダへ移動させようとしたところ、エラーが出て行えませんでした。正確にいえば・・・移動できることもあれば、移動できないこともありました。

ただ、Pure AppleScriptで書くとなんてことはない処理なので、Pure AppleScript版にルーチンだけ差し替えてそのまま使いましたが、NSFileManagerでなぜうまく処理できなかったのかをUS AppleのAppleScript Users ML上で質問。

ShaneとML上でやりとりして、「移動先に同名のファイルが存在していたから」という、ちょっと恥ずかしい初歩的な原因が判明。移動先フォルダにすでに同じ名前のファイルが存在していたら、削除するというあたりの処理を教えてもらいました。

一応、3回トライするように書き変えてみたものがこれです。NSFileManagerについては、US AppleのCocoa Dev MLでいろいろと揉めた形跡を見つけており「NSFileManagerで埒があかない場合には、NSFileHandle経由でファイルをreadしてmove先にwriteしろ」とかいう、体育会系の回答を見つけており、そういう手段をとらずにすんで本当に助かりました(^ー^;;;

AppleScript名:ファイルの移動テスト v1.3
– Created 2015-10-26 by Takaaki Naganoya
– Modified 2015-10-26 by Shane Stanley
– Modified 2015-10-26 by Takaaki Naganoya

– ネットワークごしにコピーされたファイルの取得と移動に関するテスト

use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set inFolAlias to choose folder

set pdfList to getFilePathList(inFolAlias, “.pdf”) of me
–>  {”/Users/xxxxxxx/Desktop/XXXXXPDF/00064452.PDF”, “/Users/xxxxxxx/Desktop/XXXXXPDF/00064453.PDF”, “/Users/xxxxxxx/Desktop/XXXXXPDF/00064455.PDF”}

my moveFilesWithPOSIXstrList(pdfList, “~/Pictures/DonePDF”)

–POSIX pathのリストを指定フォルダに移動
on moveFilesWithPOSIXstrList(aFileList, toFolStr)
  set pathString to current application’s NSString’s stringWithString:toFolStr
  
set newPath to pathString’s stringByExpandingTildeInPath()
  
set defM to current application’s NSFileManager’s defaultManager
  
  
repeat with i in aFileList
    if (defM’s isReadableFileAtPath:i) as boolean = true then
      set fromPath to (current application’s |NSURL|’s fileURLWithPath:i)
      
      
set fileName to fromPath’s lastPathComponent()
      
set newPathStr to (newPath’s stringByAppendingPathComponent:fileName)
      
set toPath to (current application’s |NSURL|’s fileURLWithPath:newPathStr)
      
set hitF to false
      
      
repeat 3 times
        set {theResult, theError} to (defM’s moveItemAtURL:fromPath toURL:toPath |error|:(reference))
        
        
–試してダメだった場合
        
if (theResult as boolean) = false then
          log {“Error: Something wrong with file moving…”, (theError’s |description|() as text), toPath}
          
if (toPath’s checkResourceIsReachableAndReturnError:(missing value)) as boolean then – it already exists, so try deleting
            –いったんmove先のファイルを削除
            (
defM’s removeItemAtURL:toPath |error|:(missing value))
          end if
        else
          –moveが成功した場合
          
set hitF to true
          
exit repeat
        end if
      end repeat
      
      
if hitF = false then
        tell current application
          display dialog “Serious error occured in moving files….”
        end tell
        
return
      end if
    else
      log {“Can not get originate file”} –move元のファイルが存在していなかった場合
    end if
  end repeat
end moveFilesWithPOSIXstrList

–ASOCで指定フォルダのファイルパス一覧取得(拡張子指定つき)
on getFilePathList(aFol, aExt)
  set aPath to current application’s NSString’s stringWithString:(POSIX path of aFol)
  
set aFM to current application’s NSFileManager’s defaultManager()
  
set nameList to (aFM’s contentsOfDirectoryAtPath:aPath |error|:(missing value))
  
set anArray to current application’s NSMutableArray’s alloc()’s init()
  
  
repeat with i from 1 to nameList’s |count|()
    set j to (nameList’s objectAtIndex:(i - 1)) as text
    
if (j ends with aExt) and (j does not start with “.”) then –exclude invisible files
      set newPath to (aPath’s stringByAppendingString:j)
      (
anArray’s addObject:newPath)
    end if
  end repeat
  
  
return anArray as list
end getFilePathList

★Click Here to Open This Script 

2015/10/19 指定ファイルに指定アイコン画像をつける

Cocoaの機能を用いて、指定ファイルに指定アイコン(カスタムアイコン)をつけるAppleScriptです。

アイコンの変更などという、わりと誰にでもわかりやす〜い効果が得られるものです。Pure AppleScriptだと逆立ちしてもできない(Classic Mac OSの時代にはできた気がする)処理も、AppleScriptObjCだと簡単に実現できます。

常駐型のAppletでフォルダを監視して処理させるような場合に、監視フォルダ内に書類が入ってきて処理を行うとフォルダのアイコンが変化してユーザーに「処理中」であることを視覚的にフィードバックする、とかいうのがわりといい使い道だと思います。

# 処理中のファイル数をアプレットにバッジで表示するのもけっこういいです

指定ファイルに対していわゆる「カスタムアイコン」をつけます。おまけでカスタムアイコンを削除するものも用意しておきました。

指定するアイコン画像については、ICNSファイル、TIFF画像のほか、PNGなども問題なく設定できるようですが、表示のリフレッシュタイミングがいまひとつ「God Only Knows」だったりするので、そのあたりどーにかならないものかと。

AppleScript名:指定ファイルに指定アイコン画像をつける
– Created 2015-10-19 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

set aPath to POSIX path of (choose file of type {“com.apple.icns”, “public.tiff”} with prompt “Choose Icon File”) –アイコンファイル
set aFile to POSIX path of (choose file with prompt “Choose Target File”) –設定対象のファイル

set aURL to current application’s |NSURL|’s fileURLWithPath:aPath
set aImage to current application’s NSImage’s alloc()’s initWithContentsOfURL:aURL

set aSW to current application’s NSWorkspace’s sharedWorkspace()
aSW’s setIcon:aImage forFile:aFile options:0

★Click Here to Open This Script 

AppleScript名:指定ファイルからカスタムアイコンを削除する
– Created 2015-10-19 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

set aFile to POSIX path of (choose file with prompt “Choose Target File”) –設定対象のファイル
set aSW to current application’s NSWorkspace’s sharedWorkspace()
aSW’s setIcon:(missing value) forFile:aFile options:0

★Click Here to Open This Script 

2015/10/11 ZipZap frameworkを使ってZipアーカイブ内の情報を取得

オープンソースのZipZapフレームワーク(By Pixelglow Software)を利用して、選択したZipアーカイブ中の情報を取得するAppleScriptです。

たまたまCocoa dev MLの過去ログを漁っていたら、ZipZapフレームワークを見つけました。GitHubのサイトはキーワード検索がいまひとつで、以前に検索したときにはひっかかってこなかったものです(ひととおり、めぼしいのは調べたので)。

それはともかく、GitHubのサイトからClone in DesktopでMacにXcodeプロジェクトをクローンして、Xcode 7.0.1でプロジェクトをビルド。生成したフレームワークをAppleScriptから呼び出すテストを行ってみたものです。

ほぼ、READMEに書いてある通り書いてそのまま動きました。ヘッダーファイルに書いてあるいくつかのプロパティも試してみたところ納得の結果が(READMEどおりに書いて動かないものも、他にいろいろみかけますが・・・本プロジェクトは実に素直でした)。

さまざまなプロパティをAppleScriptの型にcastしてログ表示しているため、OS X 10.11用(AppleScript version 2.5が必要)になっていますが、castしたりlog表示しなければOS X 10.10でも動きます(安全のために10.11専用に)。

例によって、OS X 10.10以降用にビルドしたZipZapフレームワークを置いておきます。興味のある方はお試しください(~/Library/Frameworks/にインストール)。

–> Download Framework Binary (OS X 10.10 or later)

AppleScript名:ASOCでZipZap frameworkを使ってZipアーカイブ内の情報を取得
– Created 2015-10-11 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.5″
use scripting additions
use framework “Foundation”
use framework “ZipZap”
–https://github.com/pixelglow/zipzap

set aPath to POSIX path of (choose file of type {“public.zip-archive”})
set oldArchive to current application’s ZZArchive’s archiveWithURL:(current application’s |NSURL|’s fileURLWithPath:aPath) |error|:(missing value)
–>  (ZZArchive)

set entryCount to oldArchive’s entries()’s |count|()
–>  180 –this zip archive includes 180 file or folders inside

set firstArchEntry to oldArchive’s entries()’s firstObject()
–>  (ZZOldArchiveEntry)

set aList to oldArchive’s entries() as list

repeat with i in aList
  set uSize to i’s uncompressedSize() as real
  
set cSize to i’s compressedSize() as real
  
set comF to i’s compressed() as boolean
  
set encF to i’s encrypted() as boolean
  
set modD to i’s lastModified() as date
  
set chkSum to i’s crc32() as text –The CRC32 code of the entry file: 0 for new entries.
  
set aFileMode to i’s fileMode() as text – The UNIX file mode for the entry: 0 for new or non-UNIX entries. This includes the file type bits.
  
set aFileName to i’s fileName() as text
  
  
log {aFileName, aFileMode, chkSum, modD, encF, comF, cSize, uSize}
  
–> 21:28:01.817 (* {”ZXingObjC.framework/”, “16877d”, “0″, date “2015年10月10日土曜日 10:07:16″, false, false, 0.0, 0.0} *)
  
–> 21:28:01.818 (* {”ZXingObjC.framework/Headers”, “41453d”, “2.393740531E+9″, date “2015年10月10日土曜日 10:07:10″, false, false, 24.0, 24.0} *)
  
–> 21:28:01.820 (* {”ZXingObjC.framework/Versions/”, “16877d”, “0″, date “2015年10月10日土曜日 10:07:10″, false, false, 0.0, 0.0} *)
  
–> 21:28:01.821 (* {”ZXingObjC.framework/Versions/3.1.0/”, “16877d”, “0″, date “2015年10月10日土曜日 10:07:16″, false, false, 0.0, 0.0} *)
  
–> 21:28:01.822 (* {”ZXingObjC.framework/Versions/3.1.0/Headers/”, “16877d”, “0″, date “2015年10月10日土曜日 10:07:16″, false, false, 0.0, 0.0} *)
  
  
–set aData to (i’s newDataWithError:false)–Uncompressed raw data
  
–log aData
end repeat

★Click Here to Open This Script