AppleScript名:ASOCで文字を逆順に v2(CJK文字などマルチバイト対応) |
— Created 2015-09-01 by Takaaki Naganoya — Modified 2015-09-01 by Shane Stanley –Consider CJK Characters & Emoji –http://stackoverflow.com/questions/6720191/reverse-nsstring-text use AppleScript version "2.4" use scripting additions use framework "Foundation" set aUUID to (current application’s NSUUID’s UUID()’s UUIDString()) as text –> "46EF17B7-CB3E-4DD9-BA8A-013D3B30A80A" set aUUID to "😀😐" & aUUID & "😀😐" –> "😀😐46EF17B7-CB3E-4DD9-BA8A-013D3B30A80A😀😐" set revUUID to reversedStr(aUUID) as text –> "😐😀A08A03B3D310-A8AB-9DD4-E3BC-7B71FE64😐😀" on reversedStr(paramStr as text) set aStr to current application’s NSString’s stringWithString:paramStr set strLength to aStr’s |length|() set revStr to current application’s NSMutableString’s stringWithCapacity:strLength set charIndex to strLength – 1 repeat while charIndex > -1 set subStrRange to aStr’s rangeOfComposedCharacterSequenceAtIndex:charIndex revStr’s appendString:(aStr’s substringWithRange:subStrRange) set charIndex to (location of subStrRange) – 1 end repeat return revStr end reversedStr |
月: 2018年2月
バージョン番号文字列からメジャーバージョンを取り出し数値として返す v4
AppleScript名:バージョン番号文字列からメジャーバージョンを取り出し数値として返す v4 |
use AppleScript version "2.5" use scripting additions use framework "Foundation" set a to "10.0.1" set b to retMajorVersionNumber(a) of me –> 10 set a to "9.10" set b to retMajorVersionNumber(a) of me –> 9 –バージョン番号文字列からメジャーバージョンを取り出し数値として返す on retMajorVersionNumber(a) set aStr to current application’s NSString’s stringWithString:a –> "10.0.1" (NSString) set aRes to (aStr’s componentsSeparatedByString:".") –> {"10","0","1"} (NSArray) set bRes to aRes’s firstObject() –> "10" (NSString) set cRes to bRes’s integerValue() –> 10 return cRes as integer end retMajorVersionNumber |
指定フォルダ以下のすべてのファイルのうち指定UTIに該当するものを取得(spotlightで処理)
AppleScript名:指定フォルダ以下のすべてのファイルを再帰で取得(spotlightで処理).scpt |
use AppleScript version "2.4" use framework "Foundation" use scripting additions use mdLib : script "Metadata Lib" version "1.0.0" –https://www.macosxautomation.com/applescript/apps/Script_Libs.html#Metadata_Lib –set theFolder to choose folder set theFolder to (path to desktop folder) set theFiles to mdLib’s searchFolders:{theFolder} searchString:"kMDItemContentType IN[c] %@" searchArgs:{"com.apple.applescript.script", "com.apple.applescript.script-bundle"} |
指定フォルダ以下のすべてのファイルを再帰で取得 v2
指定フォルダ以下のすべてのファイルを再帰で取得するAppleScriptです。
「指定フォルダ以下のファイルを取得する」やりかたは、Spotlightを使うのがベストです。ベストではあるものの、各ユーザーのHDDなりSSDは「破損している」ケースもあって、Spotligtの検索が効かない場合もあります。
また、マウントしたLAN上のファイルサーバーに対してSpotlightが効くかどうかは実際にやってみないと分かりません。OSが異なる可能性がありますし、同じmacOSであっても効くかどうかは実際に試してみるまではっきりしません(開発時に真っ先に確認するポイントでもあります。ファイルサーバーを相手に処理するつもりかどうかの確認です)。
そこで、地道に再帰処理でファイルを取得すること「も」試してみることになるわけですが、ここでFinderを使うと遅くなります。
OS X 10.6以降の64ビット化されたいわゆる「Cocoa Finder」は処理速度が低下しているため、大量のファイル処理をFinder経由で行うことは「悪手」といえます。数百個ぐらいでけっこうな処理速度の低下がみられます。1,000を超えると露骨に速度が下がります。フィルタ参照で条件をつけて抽出するのも速度低下につながります。さらに複数のフィルタ条件を指定するとアホみたいに遅くなります。Cocoa Finderの性能低下はハンパではありません。
たまに、Classic Mac OSの環境しか知らない人が久しぶりに現代の(64ビット化された)macOS上で昔と同じようにFinderに対して膨大なファイルの処理を行わせて「遅い」と文句を言っているのを見かけますが、Finder経由でのファイル処理が現実的ではないという状況を知らなければそういう感想になってしまうかもしれません。
# Classic MacOS〜macOS 10.6ぐらいまではFinder経由で行っても、極端に時間がかかることはありませんでした。それ以降の環境のお話です。また、macOS 10.7以降でも、数個〜数十程度のすくないファイルを処理する場合には、あまり問題になりません
そこで、NSFileManagerを用いてファイル処理を行うことで、「Spotlightほど速くはないものの、Finderで処理するよりははるかに高速」な処理を行えます。
AppleScript名:指定フォルダ以下のすべてのファイルを再帰で取得 v2 |
— Created 2017-08-04 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" property NSString : a reference to current application’s NSString property NSPredicate : a reference to current application’s NSPredicate property NSFileManager : a reference to current application’s NSFileManager property NSMutableArray : a reference to current application’s NSMutableArray –set aFol to POSIX path of (choose folder) set aFol to POSIX path of (path to desktop folder) –set aList to retFullPathWithinAFolderWithRecursive(aFol) of me set bList to retFullPathWithinAFolderWithRecursiveFilterByExt(aFol, "scpt") of me –set cList to retFilenameWithinAFolderWithRecursiveFilterByExt(aFol, {"scpt", "scptd"}) of me –set dList to retFullPathWithinAFolderWithRecursiveFilterByExtAndFileNameString(aFol, "png", "スクリーン") of me –set eList to retFullPathWithinAFolderWithRecursiveFilterByExtAndFileNameString(aFol, {"scpt", "scptd"}, "並列") of me –指定フォルダ以下のすべてのファイルを再帰で取得 on retFilenamesWithinAFolderWithRecursive(aFol) set anArray to NSMutableArray’s array() set aPath to NSString’s stringWithString:aFol set dirEnum to NSFileManager’s defaultManager()’s enumeratorAtPath:aPath repeat set aName to (dirEnum’s nextObject()) if aName = missing value then exit repeat set aFullPath to aPath’s stringByAppendingPathComponent:aName anArray’s addObject:(aFullPath’s lastPathComponent()’s stringByDeletingPathExtension() as string) end repeat return anArray as list end retFilenamesWithinAFolderWithRecursive –指定フォルダ以下のすべてのファイルを再帰で取得 on retFullPathWithinAFolderWithRecursive(aFol) set anArray to NSMutableArray’s array() set aPath to NSString’s stringWithString:aFol set dirEnum to NSFileManager’s defaultManager()’s enumeratorAtPath:aPath repeat set aName to (dirEnum’s nextObject()) if aName = missing value then exit repeat set aFullPath to aPath’s stringByAppendingPathComponent:aName anArray’s addObject:(aFullPath’s lastPathComponent()’s stringByDeletingPathExtension() as string) end repeat return anArray as list end retFullPathWithinAFolderWithRecursive –指定フォルダ以下のすべてのファイルを再帰で取得(拡張子で絞り込み) on retFilenameWithinAFolderWithRecursiveFilterByExt(aFol, aExt) set anArray to NSMutableArray’s array() set aPath to NSString’s stringWithString:aFol set dirEnum to NSFileManager’s defaultManager()’s enumeratorAtPath:aPath repeat set aName to (dirEnum’s nextObject()) if aName = missing value then exit repeat set aFullPath to aPath’s stringByAppendingPathComponent:aName anArray’s addObject:aFullPath end repeat set thePred to NSPredicate’s predicateWithFormat:"pathExtension == [c]%@" argumentArray:{aExt} set bArray to anArray’s filteredArrayUsingPredicate:thePred return bArray as list end retFilenameWithinAFolderWithRecursiveFilterByExt –指定フォルダ以下のすべてのファイルを再帰で取得(拡張子で絞り込み) on retFullPathWithinAFolderWithRecursiveFilterByExt(aFol, aExt) set anArray to NSMutableArray’s array() set aPath to NSString’s stringWithString:aFol set dirEnum to NSFileManager’s defaultManager()’s enumeratorAtPath:aPath repeat set aName to (dirEnum’s nextObject()) if aName = missing value then exit repeat set aFullPath to aPath’s stringByAppendingPathComponent:aName anArray’s addObject:aFullPath end repeat set thePred to NSPredicate’s predicateWithFormat:"pathExtension == [c]%@" argumentArray:{aExt} set bArray to anArray’s filteredArrayUsingPredicate:thePred return bArray as list end retFullPathWithinAFolderWithRecursiveFilterByExt –指定フォルダ以下のすべてのファイルを再帰で取得(拡張子リストで絞り込み) on retFullPathWithinAFolderWithRecursiveFilterByExtList(aFol, aExtList) set anArray to NSMutableArray’s array() set aPath to NSString’s stringWithString:aFol set dirEnum to NSFileManager’s defaultManager()’s enumeratorAtPath:aPath repeat set aName to (dirEnum’s nextObject()) if aName = missing value then exit repeat set aFullPath to aPath’s stringByAppendingPathComponent:aName anArray’s addObject:aFullPath end repeat set thePred to NSPredicate’s predicateWithFormat:"pathExtension IN [c]%@" argumentArray:{aExtList} set bArray to anArray’s filteredArrayUsingPredicate:thePred return bArray as list end retFullPathWithinAFolderWithRecursiveFilterByExtList –指定フォルダ以下のすべてのファイルを再帰で取得(文字列と拡張子で絞り込み) on retFullPathWithinAFolderWithRecursiveFilterByExtListAndFileNameString(aFol, aExt, aNameString) set anArray to NSMutableArray’s array() set aPath to NSString’s stringWithString:aFol set dirEnum to NSFileManager’s defaultManager()’s enumeratorAtPath:aPath repeat set aName to (dirEnum’s nextObject()) if aName = missing value then exit repeat set aFullPath to aPath’s stringByAppendingPathComponent:aName anArray’s addObject:aFullPath end repeat set thePred to NSPredicate’s predicateWithFormat:"pathExtension == [c]%@ && lastPathComponent CONTAINS %@" argumentArray:{aExt, aNameString} set bArray to anArray’s filteredArrayUsingPredicate:thePred return bArray as list end retFullPathWithinAFolderWithRecursiveFilterByExtListAndFileNameString –指定フォルダ以下のすべてのファイルを再帰で取得(文字列と拡張子リストで絞り込み) on retFullPathWithinAFolderWithRecursiveFilterByExtAndFileNameString(aFol, aExtList, aNameString) set anArray to NSMutableArray’s array() set aPath to NSString’s stringWithString:aFol set dirEnum to NSFileManager’s defaultManager()’s enumeratorAtPath:aPath repeat set aName to (dirEnum’s nextObject()) if aName = missing value then exit repeat set aFullPath to aPath’s stringByAppendingPathComponent:aName anArray’s addObject:aFullPath end repeat set thePred to NSPredicate’s predicateWithFormat:"pathExtension IN [c]%@ && lastPathComponent CONTAINS %@" argumentArray:{aExtList, aNameString} set bArray to anArray’s filteredArrayUsingPredicate:thePred return bArray as list end retFullPathWithinAFolderWithRecursiveFilterByExtAndFileNameString |
指定ボリウムをマウント
AppleScript名:指定ボリウムをマウント |
— Created 2015-12-01 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set aPath to current application’s |NSURL|’s URLWithString:"afp://MBA13.local/maro" set ws to current application’s NSWorkspace’s sharedWorkspace() ws’s openURL:aPath |
CocoaでDiskSpace(%)を求める
AppleScript名:CocoaでDiskSpace(%)を求める |
— Created 2015-04-01 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set aPath to current application’s NSString’s stringWithString:"/" set fileAttr to current application’s NSFileManager’s defaultManager()’s attributesOfFileSystemForPath:aPath |error|:(missing value) set fRes to (fileAttr’s objectForKey:(current application’s NSFileSystemFreeSize)) as string set aDecNum to current application’s NSDecimalNumber’s decimalNumberWithString:fRes set aFreeNum to aDecNum’s decimalNumberByDividingBy:(current application’s NSDecimalNumber’s decimalNumberWithString:"1000000000") –"G" Bytes for Storage set bFreeNum to aFreeNum as real –> 84.058387756348 |
CocoaでDiskSpace(Bytes)を求める
AppleScript名:CocoaでDiskSpace(Bytes)を求める |
— Created 2015-04-02 by Shane Stanley use AppleScript version "2.4" use scripting additions use framework "Foundation" usedSpace("/") –> 8.4346003456E+10 usedSpace2("/") –> 8.4345450496E+10 usedSpaceString("/") –> "84.35 GB" usedSpaceLongString("/") –> "45.77 GB (45,772,857,344 bytes)"–English user environment –> "45.77 GB (45,772,857,344 バイト)"–Japanese user environment tell application "Finder" free space of startup disk end tell –> 4.5784592712E+10 on usedSpace(volumePath) set theNSURL to current application’s class "NSURL"’s fileURLWithPath:volumePath –considering "ASOC in Xcode" set {theResult, theSize} to theNSURL’s getResourceValue:(reference) forKey:(current application’s NSURLVolumeAvailableCapacityKey) |error|:(missing value) return theSize as real — integer may be too big for AS end usedSpace on usedSpace2(volumePath) set fileAttr to current application’s NSFileManager’s defaultManager()’s attributesOfFileSystemForPath:volumePath |error|:(missing value) return (fileAttr’s objectForKey:(current application’s NSFileSystemFreeSize)) as real — integer may be too big for AS end usedSpace2 on usedSpaceString(volumePath) set fileAttr to current application’s NSFileManager’s defaultManager()’s attributesOfFileSystemForPath:volumePath |error|:(missing value) set fRes to fileAttr’s objectForKey:(current application’s NSFileSystemFreeSize) –Formatting set sizeString to current application’s NSByteCountFormatter’s stringFromByteCount:fRes countStyle:(current application’s NSByteCountFormatterCountStyleDecimal) return sizeString as text end usedSpaceString on usedSpaceLongString(volumePath) set fileAttr to current application’s NSFileManager’s defaultManager()’s attributesOfFileSystemForPath:volumePath |error|:(missing value) set fRes to fileAttr’s objectForKey:(current application’s NSFileSystemFreeSize) –Formatting set theFormatter to current application’s NSByteCountFormatter’s alloc()’s init() theFormatter’s setCountStyle:(current application’s NSByteCountFormatterCountStyleDecimal) theFormatter’s setIncludesActualByteCount:true set sizeString to theFormatter’s stringFromByteCount:fRes return sizeString as text end usedSpaceLongString |
指定フォルダが所属しているDiskの空き容量をGバイト単位で返す
AppleScript名:指定フォルダが所属しているDiskの空き容量をGバイト単位で返す |
— Created 2015-04-02 by Shane Stanley use AppleScript version "2.4" use scripting additions use framework "Foundation" set aFol to choose folder set aFolPOSIX to POSIX path of aFol set fRes to freeStorageSpaceG(aFolPOSIX) –指定フォルダが所属しているDiskの空き容量をGバイト単位で返す on freeStorageSpaceG(volumePath) set fileAttr to current application’s NSFileManager’s defaultManager()’s attributesOfFileSystemForPath:volumePath |error|:(missing value) set fileFree to (fileAttr’s objectForKey:(current application’s NSFileSystemFreeSize)) set sizeString to current application’s NSByteCountFormatter’s stringFromByteCount:fileFree countStyle:(current application’s NSByteCountFormatterCountStyleDecimal) return sizeString as text end freeStorageSpaceG |
指定ボリウム(サーバーボリウム)の空き容量を調べる
AppleScript名:指定ボリウム(サーバーボリウム)の空き容量を調べる |
— Created 2015-05-14 by Shane Stanley use AppleScript version "2.4" use scripting additions use framework "Foundation" set serverName to "maro" set aRes to getVolumeFreeSpace(serverName) of me on getVolumeFreeSpace(serverName) set anNSURL to (current application’s |NSURL|’s fileURLWithPath:"/Volumes")’s URLByAppendingPathComponent:serverName set theResult to (anNSURL’s checkResourceIsReachableAndReturnError:(missing value)) as boolean if not theResult then — not mounted, so handle error return false end if set {theResult, theSpare} to anNSURL’s getResourceValue:(reference) forKey:(current application’s NSURLVolumeAvailableCapacityKey) |error|:(missing value) if theResult as boolean then set spareString to (current application’s NSByteCountFormatter’s stringFromByteCount:theSpare countStyle:(current application’s NSByteCountFormatterCountStyleFile)) as text else — couldn’t get the value, so handle error error end if end getVolumeFreeSpace |
SDカードを検出
マウントされたドライブのうちSDカードに相当するものを検出するAppleScriptです。
ただし、iMac Proで採用されたUHS‑II対応のSDカードスロット+UHS-II対応のSDカードがどのように見えるかは実機がないので確認できません。
exFATのことも考えると、「MSDOS format」を抽出条件に入れないほうがいいのかもしれません。
AppleScript名:SDカードを検出 |
— Created 2016-10-04 by Takaaki Naganoya — 2016 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" tell application "Finder" set driveList to every disk whose format is (MSDOS format) and ejectable is true and startup is false repeat with i in driveList set myDisk to disk of (first item of i) set myMountPoint to POSIX path of (myDisk as alias) –> "/Volumes/JVCCAM_SD/" –> "/Volumes/RICOHDCX/" set sdRes to detectSDCard(myMountPoint) of me –> true –SD Card, false –Not SD Card end repeat end tell on detectSDCard(myMountPoint as string) set resData to runCommandString("system_profiler -xml SPStorageDataType") of me set aaDict to (readPlistFromStr(resData) of me) as list set aDictList to (_items of first item of aaDict) repeat with i in aDictList set j to contents of i set aMountPoint to (mount_point of j) as string –> "/Volumes/JVCCAM_SD" –> "/Volumes/RICOHDCX" if aMountPoint is not equal to "/" then if ((aMountPoint & "/") is equal to myMountPoint) then set aDevName to words of (device_name of physical_drive of j) set aMediaName to words of (media_name of physical_drive of j) –SD/SDHC/SDXCのカード検出 set aDevF to ("SD" is in aDevName) or ("SDHC" is in aDevName) or ("SDXC" is in aDevName) set aMediaF to ("SD" is in aMediaName) or ("SDHC" is in aMediaName) or ("SDXC" is in aMediaName) if (aDevF and aMediaF) then return true end if end if end repeat return false end detectSDCard –文字列で与えたシェルコマンドを実行する on runCommandString(commandStr as string) set aPipe to current application’s NSPipe’s pipe() set aTask to current application’s NSTask’s alloc()’s init() aTask’s setLaunchPath:"/bin/sh" aTask’s setArguments:{"-c", current application’s NSString’s stringWithFormat_("%@", commandStr)} aTask’s setStandardOutput:aPipe set aFile to aPipe’s fileHandleForReading() aTask’s |launch|() return current application’s NSString’s alloc()’s initWithData:(aFile’s readDataToEndOfFile()) encoding:(current application’s NSUTF8StringEncoding) end runCommandString –stringのplistを読み込んでRecordに on readPlistFromStr(theString) set aSource to current application’s NSString’s stringWithString:theString set pListData to aSource’s dataUsingEncoding:(current application’s NSUTF8StringEncoding) set aPlist to current application’s NSPropertyListSerialization’s propertyListFromData:pListData mutabilityOption:(current application’s NSPropertyListImmutable) |format|:(current application’s NSPropertyListFormat) errorDescription:(missing value) return aPlist end readPlistFromStr |
指定容量の指定名称のRAMディスクを作成する
指定容量+指定名称のRAMディスクを作成するAppleScriptです。
SSDのアクセス速度が意外と処理のボトルネックになることがあるので(並列処理時とか)、ごくまれにRAMディスクを作って処理することがあります。
ただ、ベンチマーク値では最新機種の方がこれ(↑)よりも高速なSSDを搭載していたりするので、なかなか感慨深いものがあります。実際に処理を行わせてみるとベンチマーク値ほどには差が出なかったりもします。
AppleScript名:指定容量の指定名称のRAMディスクを作成する |
— Created 2017-01-24 by Takaaki Naganoya — 2017 Piyomaru Software –https://www.tekrevue.com/tip/how-to-create-a-4gbs-ram-disk-in-mac-os-x/ use AppleScript version "2.4" use scripting additions use framework "Foundation" set dName to "RAM Disk" set dCapacity to 512 * 2 * 1000 –512MB set aCmd to "diskutil erasevolume HFS+ ’" & dName & "’ `hdiutil attach -nomount ram://" & (dCapacity as string) & "`" try do shell script aCmd end try |
指定フォルダ内のPDFの1ページ目をすべて別のPDFにまとめる
AppleScript名:指定フォルダ内のPDFの1ページ目をすべて別のPDFにまとめる |
— Created 2017-09-12 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "QuartzCore" property |NSURL| : a reference to current application’s |NSURL| property NSPredicate : a reference to current application’s NSPredicate property NSFileManager : a reference to current application’s NSFileManager property PDFDocument : a reference to current application’s PDFDocument property NSMutableArray : a reference to current application’s NSMutableArray property NSURLIsDirectoryKey : a reference to current application’s NSURLIsDirectoryKey property NSDirectoryEnumerationSkipsHiddenFiles : a reference to current application’s NSDirectoryEnumerationSkipsHiddenFiles property NSDirectoryEnumerationSkipsPackageDescendants : a reference to current application’s NSDirectoryEnumerationSkipsPackageDescendants property NSDirectoryEnumerationSkipsSubdirectoryDescendants : a reference to current application’s NSDirectoryEnumerationSkipsSubdirectoryDescendants set aFol to POSIX path of (choose folder with prompt "Choose folder" default location (path to pictures folder)) set targPDF to POSIX path of (choose file name with prompt "Choose File Name" default location (path to desktop folder) default name ((do shell script "uuidgen") & ".pdf")) set pRes to gatherEachFirstPage(aFol, targPDF) of me on gatherEachFirstPage(aFol, targPDF) set aURL to (|NSURL|’s fileURLWithPath:targPDF) set outPDFdoc to PDFDocument’s alloc()’s init() set aList to my getFilesByExtension:{"pdf"} fromDirectory:(aFol) set outPDFPageCount to 0 repeat with i in aList –集めたPDFの1ページ目を取得 set bURL to (|NSURL|’s fileURLWithPath:(POSIX path of i)) set bPDFdoc to (PDFDocument’s alloc()’s initWithURL:bURL) set bPage to (bPDFdoc’s pageAtIndex:0) –first page –まとめ先のPDFに追記 (outPDFdoc’s insertPage:bPage atIndex:outPDFPageCount) set outPDFPageCount to outPDFPageCount + 1 end repeat return (outPDFdoc’s writeToURL:aURL) as boolean end gatherEachFirstPage –指定フォルダ内の指定拡張子のファイルを抽出する on getFilesByExtension:listOfExtensions fromDirectory:sourceFolder set fileManager to NSFileManager’s defaultManager() set aURL to |NSURL|’s fileURLWithPath:sourceFolder set theOptions to ((NSDirectoryEnumerationSkipsPackageDescendants) as integer) + ((NSDirectoryEnumerationSkipsHiddenFiles) as integer) set directoryContents to fileManager’s contentsOfDirectoryAtURL:aURL includingPropertiesForKeys:{} options:theOptions |error|:(missing value) set foundItemList to NSPredicate’s predicateWithFormat_("pathExtension.lowercaseString IN %@", listOfExtensions) set foundItemList to directoryContents’s filteredArrayUsingPredicate:foundItemList # Return as a list POSIX Paths set foundItemList to (foundItemList’s valueForKey:"path") as list return foundItemList end getFilesByExtension:fromDirectory: |
PDFをページごとに分解してJPEGで保存する v3
AppleScript名:PDFをページごとに分解してJPEGで保存する v3 |
— 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 — Modified 2016-07-27 by Takaaki Naganoya–Zero padding function, Consider Retina Env — 2016 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "Quartz" 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 –1.0 — 0.0 = max jpeg compression, 1.0 = none –Detect Retina Environment set retinaF to current application’s NSScreen’s mainScreen()’s backingScaleFactor() if retinaF = 1.0 then set aScale to 2.0 –Non Retina Env else set aScale to 1.0 –Retina Env end if –PDFをページごとに分割してJPEGでファイル書き出し repeat with i from 0 to (pCount – 1) –Pick Up a PDF page as an image 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) –Resize Image set pointSize to thisDoc’s |size|() set newSize to current application’s NSMakeSize((pointSize’s width) * aScale, (pointSize’s height) * aScale) set newImage to (current application’s NSImage’s alloc()’s initWithSize:newSize) newImage’s lockFocus() (thisDoc’s setSize:newSize) (current application’s NSGraphicsContext’s currentContext()’s setImageInterpolation:(current application’s NSImageInterpolationHigh)) (thisDoc’s drawAtPoint:(current application’s NSZeroPoint) fromRect:(current application’s CGRectMake(0, 0, newSize’s width, newSize’s height)) operation:(current application’s NSCompositeCopy) fraction:1.0) newImage’s unlockFocus() –Save Image as JPEG set theData to newImage’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 zText to retZeroPaddingText((i + 1), 4) of me set outPath to addString_beforeExtensionIn_addingExtension_("_" & zText, 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: on retZeroPaddingText(aNum as integer, aDigitNum as integer) if aNum > (((10 ^ aDigitNum) as integer) – 1) then return "" –Range Check set aFormatter to current application’s NSNumberFormatter’s alloc()’s init() aFormatter’s setUsesGroupingSeparator:false aFormatter’s setAllowsFloats:false aFormatter’s setMaximumIntegerDigits:aDigitNum aFormatter’s setMinimumIntegerDigits:aDigitNum aFormatter’s setPaddingCharacter:"0" set aStr to aFormatter’s stringFromNumber:(current application’s NSNumber’s numberWithFloat:aNum) return aStr as string end retZeroPaddingText |
PDFの指定ページを削除 v4(複数ページ一括指定)
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" 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: |
PDFの指定ページを削除 v3(PDFDocument経由でアクセス)
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 |
2つのPDFのテキストの指定ページの差分をVimdiffで表示する v2
2つのPDFの指定ページのテキスト内容をvimdiffで差分表示するAppleScriptです。
Terminal上でvimdiffによる差分比較を表示します。Mac AppStoreに出したアプリ(Double PDF)の部品として使ったらリジェクトされました。Terminal.appを使うものはリジェクトなんだそうで。
半日ぐらいですぐに別のルーチンに差し替えたので本Scriptはあっという間に闇から闇へと葬られました。
FileMergeがAppleScript用語辞書を持っていて単独配布されていたらいろいろ問題は解決される気がします。
AppleScript名:2つのPDFのテキストの指定ページの差分をVimdiffで表示する v2 |
— Created 2017-06-24 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "Quartz" set aPageNum to 103 –diffを表示する対象ページ set aPath to POSIX path of (choose file of type {"com.adobe.pdf"}) set a1Name to makeTmpFileStrPath(aPath) of me set aStr to retBodyStringFromPdf(aPath, aPageNum) of me set aStr1 to cleanUpText(aStr as string, string id 13, string id 10) of me –改行コードをCRからLFに置換 aStr1’s writeToFile:a1Name atomically:true encoding:(current application’s NSUTF8StringEncoding) |error|:(missing value) set bPath to POSIX path of (choose file of type {"com.adobe.pdf"}) set b1Name to makeTmpFileStrPath(bPath) of me set bStr to retBodyStringFromPdf(bPath, aPageNum) of me set bStr1 to cleanUpText(bStr as string, string id 13, string id 10) of me –改行コードをCRからLFに置換 bStr1’s writeToFile:b1Name atomically:true encoding:(current application’s NSUTF8StringEncoding) |error|:(missing value) set sText to "vimdiff " & quoted form of (a1Name as string) & " " & quoted form of (b1Name as string) doComInTerminalWindow(sText) of me on makeTmpFileStrPath(aPath) set aTmpPath to current application’s NSString’s stringWithString:(POSIX path of (path to temporary items)) set aUUID to current application’s NSUUID’s UUID()’s UUIDString() set aName to aUUID’s stringByAppendingPathExtension:"txt" set a1FullPath to (aTmpPath’s stringByAppendingString:aName) return a1FullPath end makeTmpFileStrPath on retBodyStringFromPdf(thePath as string, targPageNum as integer) set anNSURL to (current application’s |NSURL|’s fileURLWithPath:thePath) set theDoc to current application’s PDFDocument’s alloc()’s initWithURL:anNSURL set theCount to theDoc’s pageCount() as integer if targPageNum > theCount then return "" set aPage to (theDoc’s pageAtIndex:(targPageNum – 1)) set tmpStr to (aPage’s |string|()) return tmpStr end retBodyStringFromPdf on doComInTerminalWindow(aCMD) using terms from application "Terminal" tell application id "com.apple.Terminal" activate set wCount to count (every window whose visible is true) if wCount = 0 then –ウィンドウが1枚も表示されていない場合 do script "pwd" activate set size of front window to {1280, 700} do script aCMD in front window else –すでにウィンドウが表示されている場合 do script "pwd" in front window activate set size of front window to {1280, 700} do script aCMD in front window end if end tell end using terms from end doComInTerminalWindow on cleanUpText(someText, targStr, repStr) set theString to current application’s NSString’s stringWithString:someText set targString to current application’s NSString’s stringWithString:targStr set repString to current application’s NSString’s stringWithString:repStr set theString to theString’s stringByReplacingOccurrencesOfString:targString withString:repString options:(current application’s NSRegularExpressionSearch) range:{location:0, |length|:length of someText} return theString end cleanUpText |
PDFから本文テキストを抽出して配列にストアして文字列検索 v2
指定のPDFの本文テキストから、同義語をリストで与えて文字列検索を行い、出現ページのページ数を返すAppleScriptです。
PDFからの索引作成を行うために作成したものです。最初に対象PDFから本文テキストを(ページごとに)抽出してテキスト検索キャッシュを作成。
まずはこのテキスト検索キャッシュへの検索を行ったのち、ヒットしなかったらPDFに対して文字列検索を行います。
筆者の実行環境(MacBook Pro Retina 2012)で483ページある「AppleScript最新リファレンス」に対して本Scriptを実行して4.66 secぐらいです。
テキスト検索キャッシュの効果を発揮するためには、索引作成の同義語リストをまとめて与えて処理するのがベストでしょう。
AppleScript名:PDFから本文テキストを抽出して配列にストアして文字列検索 v2 |
— Created 2017-06-18 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "Quartz" use bPlus : script "BridgePlus" –検索対象の語群 set sList to {"Piyomaru Software", "ぴよまるソフトウェア"} –considering case set thePath to POSIX path of (choose file of type {"com.adobe.pdf"}) set aRes to findWordListInPDFContents(thePath, sList) of me –> {1, 3, 4, 71, 72, 75, 95, 96, 97, 98, 420, 429, 479, 483} —PDF本文テキスト中から、語群で出現ページをリストで取得(索引作成用) on findWordListInPDFContents(thePOSIXPath as string, sList as list) script spdPDF property textCache : missing value property aList : {} end script –PDFのテキスト内容をあらかじめページごとに読み取って、検索用のテキストキャッシュを作成 set anNSURL to (current application’s |NSURL|’s fileURLWithPath:thePOSIXPath) set theDoc to current application’s PDFDocument’s alloc()’s initWithURL:anNSURL set theCount to theDoc’s pageCount() as integer set (textCache of spdPDF) to current application’s NSMutableArray’s new() repeat with i from 0 to (theCount – 1) set aPage to (theDoc’s pageAtIndex:i) set tmpStr to (aPage’s |string|()) ((textCache of spdPDF)’s addObject:{pageIndex:i + 1, pageString:tmpStr}) end repeat –主にテキストキャッシュを対象にキーワード検索 repeat with s in sList –❶部分一致で抽出 set bRes to ((my filterRecListByLabel1((textCache of spdPDF), "pageString contains ’" & s & "’"))’s pageIndex) as list –❷、❶のページ単位のテキスト検索で見つからなかった場合(ページ間でまたがっている場合など) if bRes = {} then set bRes to {} set theSels to (theDoc’s findString:s withOptions:0) repeat with aSel in theSels set thePage to (aSel’s pages()’s objectAtIndex:0)’s label() set curPage to (thePage as integer) if curPage is not in bRes then set the end of bRes to curPage end if end repeat end if set the end of (aList of spdPDF) to bRes end repeat –2D list to 1D list conversion (Flatten) load framework set bList to (current application’s SMSForder’s arrayByFlattening:(aList of spdPDF)) as list –Uniquefy set cList to uniquifyList(bList) of me –Sort 1D List set anArray to current application’s NSArray’s arrayWithArray:cList set sortRes1 to (anArray’s sortedArrayUsingSelector:"compare:") as list of string or string –as anything set (textCache of spdPDF) to "" –Purge set (aList of spdPDF) to {} –Purge return sortRes1 end findWordListInPDFContents –リストに入れたレコードを、指定の属性ラベルの値で抽出 on filterRecListByLabel1(aRecList as list, aPredicate as string) set aArray to current application’s NSArray’s arrayWithArray:aRecList set aPredicate to current application’s NSPredicate’s predicateWithFormat:aPredicate set filteredArray to aArray’s filteredArrayUsingPredicate:aPredicate return filteredArray end filterRecListByLabel1 on uniquifyList(aList as list) set aArray to current application’s NSArray’s arrayWithArray:aList set bArray to aArray’s valueForKeyPath:"@distinctUnionOfObjects.self" return bArray as list end uniquifyList |
指定PDFの最初のページからアノテーションを取得する
AppleScript名:指定PDFの最初のページからアノテーションを取得する |
— Created 2017-06-08 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "Quartz" set aHFSPath to (choose file of type {"com.adobe.pdf"} with prompt "Choose a PDF with Annotation") 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 firstPage to (aPDFdoc’s pageAtIndex:0) –> (PDFPage) PDFPage, label 1 set anoList to (firstPage’s annotations()) as list if anoList = {missing value} then return –指定PDF中にAnotationが存在しなかった log anoList (* {(PDFAnnotationMarkup) Type: ’Highlight’, Bounds: (81, 624) [434, 53] , (PDFAnnotationSquare) Type: ’Square’, Bounds: (50, 419) [212, 162] , (PDFAnnotationSquare) Type: ’Square’, Bounds: (301, 107) [244, 484] } *) repeat with i in anoList set aBounds to i’s |bounds|() log aBounds (* {origin:{x:80.79, y:624.4106}, size:{width:433.6944, height:52.8918}} *) (* {origin:{x:50.05553, y:419.1671}, size:{width:212.27807, height:162.3308}} *) (* {origin:{x:300.6213, y:106.8405}, size:{width:244.0961, height:484.4566}} *) end repeat |
指定PDFの最初のページからアノテーションを削除する
AppleScript名:指定PDFの最初のページからアノテーションを削除する |
— Created 2017-06-09 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "Quartz" set aHFSPath to (choose file of type {"com.adobe.pdf"} with prompt "Choose a PDF with Annotation") 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 firstPage to (aPDFdoc’s pageAtIndex:0) set anoList to (firstPage’s annotations()) as list repeat with i in anoList (firstPage’s removeAnnotation:i) end repeat aPDFdoc’s writeToFile:aPOSIX |
指定PDFのすべてのページからすべてのアノテーションを削除する
AppleScript名:指定PDFのすべてのページからすべてのアノテーションを削除する |
— Created 2017-06-09 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "Quartz" set aHFSPath to (choose file of type {"com.adobe.pdf"} with prompt "Choose a PDF with Annotation") 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() repeat with ii from 0 to (pCount – 1) set firstPage to (aPDFdoc’s pageAtIndex:ii) set anoList to (firstPage’s annotations()) as list repeat with i in anoList (firstPage’s removeAnnotation:i) end repeat end repeat aPDFdoc’s writeToFile:aPOSIX |