ドラッグ&ドロップでフォルダを同期するフォルダアクション [プログラミング]
ちょっと時間があいてしまった。
いきさつ、なにがやりたいか、技術的な問題は何か、といったことは前回説明したけど、今日は実際に動作するApple Scriptを示して、その使い方を説明する。
こういうのってどうだろ?面白いかな?
バックアップしたいフォルダを、バックアップ先のフォルダの中にコマンド+オプションキーを同時に押しながらドラッグ&ドロップする。
しばらくすると「同期が完了しました」というダイアログ
が現れて、
ただし、バックアップ元とバックアップ先のフォルダの名前は、かならず同じにしておくことが必要。
新規ファイルを作ってこのページの下の方にあるスクリプトをコピペする。
下の図に示したフォルダ(自分の「ライブラリ」のなかの「Scripts」の「Folder Action Scripts」)に適当な名前(ここではrsyncFolder)をつけて保存する。
フォルダがない場合はこの通りの正確な名前で作っておく。
バックアップ元ではなく、バックアップ先のフォルダアクションを設定する。
さっき保存したスクリプトが表示されるはずなので、それを選んで「関連付ける」ボタンを押す。
これで完了。
もちろん、ローカルHDD内の別の場所にあるフォルダだけでなく、ローカルとUSBメモリのあいだや、ネットワーク上のフォルダでも動作する。ただし、ローカル以外のドライブがHFS+でフォーマットされていないと、フォルダアクションの設定はドライブを取り出すと忘れられてしまうので要注意。
スクリプトからFinderを呼んで
フォルダアクションはFinderの動作のあとに起動されるので、エイリアスファイルをドロップするのがミソ。また、rsyncは正常に終わったら何も出力しないので、それでエラーがあったかどうか判断をしている。
ところで、Apple Scriptってローカライズはどうやってやるんだろう。スクリプトに日本語の文字列が埋まってしまう。Cocoaみたいな方法ってあるのかしら。
いきさつ、なにがやりたいか、技術的な問題は何か、といったことは前回説明したけど、今日は実際に動作するApple Scriptを示して、その使い方を説明する。
こういうのってどうだろ?面白いかな?
これはなにか?
ドラッグ&ドロップでフォルダの内容を同期するフォルダアクション。バックアップしたいフォルダを、バックアップ先のフォルダの中にコマンド+オプションキーを同時に押しながらドラッグ&ドロップする。
しばらくすると「同期が完了しました」というダイアログ
が現れて、
- バックアップ先のフォルダにないものはコピーする
- 古いファイルは置き換える
ただし、バックアップ元とバックアップ先のフォルダの名前は、かならず同じにしておくことが必要。
やりかた
まず、ユーティリティフォルダにある「Apple Scriptエディタ」を起動する。新規ファイルを作ってこのページの下の方にあるスクリプトをコピペする。
下の図に示したフォルダ(自分の「ライブラリ」のなかの「Scripts」の「Folder Action Scripts」)に適当な名前(ここではrsyncFolder)をつけて保存する。
フォルダがない場合はこの通りの正確な名前で作っておく。
バックアップ元ではなく、バックアップ先のフォルダアクションを設定する。
さっき保存したスクリプトが表示されるはずなので、それを選んで「関連付ける」ボタンを押す。
これで完了。
もちろん、ローカルHDD内の別の場所にあるフォルダだけでなく、ローカルとUSBメモリのあいだや、ネットワーク上のフォルダでも動作する。ただし、ローカル以外のドライブがHFS+でフォーマットされていないと、フォルダアクションの設定はドライブを取り出すと忘れられてしまうので要注意。
うごかないとき
1.コマンド+オプションキーを押しながらバックアップ先のフォルダの中にドロップしているか?
このとき、ポインタが「エイリアスを作る」場合の形(曲がった矢印)になっているか確認。2.スクリプトを保存したフォルダの名前があっているか?
正確でないと、「フォルダアクション設定」でスクリプトが表示されない。3.rsyncがインストールされているか?
実際の同期作業はrsyncというunixコマンドを使っている。ターミナルから% ls /usr/bin/rsyncと入力して(%はプロンプトで入力は「ls」以降)、なにも表示されなければ、rsyncは存在しない。Mac OS Xでは標準でインストールされているはずなので、あとから消されたと考えられる。rsyncだけインストールするか、OS再インストール。
なにをしているか
フォルダにファイルを追加したときに実行されるon adding folder itemsフォルダアクションを使っている。オプションキーとコマンドキーを押しながらドロップすると、エイリアスファイルがそのフォルダの中に作られる。スクリプトからFinderを呼んで
- ドロップされたのはエイリアスファイルか?
- そのエイリアスファイルの実体はフォルダか?
- その名前がフォルダアクションの設定されているフォルダと同じか?
フォルダアクションはFinderの動作のあとに起動されるので、エイリアスファイルをドロップするのがミソ。また、rsyncは正常に終わったら何も出力しないので、それでエラーがあったかどうか判断をしている。
スクリプト
コンパイル済みのApple Scriptをダウンロードしてもらってもいいんだけど、バイトコードが含まれてしまうので、スクリプトだけをここに示す。ひとつのスクリプトにせずに、いくつかに分割した方が読みやすかった。けどもういいや。ところで、Apple Scriptってローカライズはどうやってやるんだろう。スクリプトに日本語の文字列が埋まってしまう。Cocoaみたいな方法ってあるのかしら。
property nameOfTheAuther : "decafish" property rsyncFolderLogName : "rsyncFolder" on adding folder items to thisFolder after receiving aliasList try set droppedItem to the first item of aliasList -- Finderからファイルの情報を得る tell application "Finder" set nameOfThisFolder to name of thisFolder set droppedKind to kind of droppedItem set isAliasOfFolder to false set nameOfOriginal to "" if droppedKind is equal to "エイリアス" then set droppedOriginal to original item of droppedItem set nameOfOriginal to name of droppedOriginal if class of droppedOriginal is equal to folder then set droppedOriginalFile to droppedOriginal as alias set isAliasOfFolder to true end if end if end tell if isAliasOfFolder and (nameOfOriginal is equal to nameOfThisFolder) then set thisPath to POSIX path of thisFolder set droppedPath to POSIX path of droppedOriginalFile set rsyncLogPath to ("/tmp/" & rsyncFolderLogName & ".log") set rsyncCommand to ("/usr/bin/rsync -a " & droppedPath & " " & thisPath & " > " & rsyncLogPath) -- rsyncコマンド発行 do shell script rsyncCommand set rsyncLogFile to (POSIX file rsyncLogPath) as alias tell application "Finder" if (size of rsyncLogFile) is not equal to 0 then set moveLogDestination to ("~/Library/Logs/" & rsyncFolderLogName & ".log") do shell script ("mv " & rsyncLogPath & " " & moveLogDestination) error ("同期に失敗しました。詳細はコンソールから" & rsyncFolderLogName & "を確認して下さい。") else do shell script ("rm " & rsyncLogPath) end if delete droppedItem end tell display dialog ("\"" & nameOfThisFolder & "\"フォルダを同期しました。") (* else display dialog "do nothing" *) end if on error errStr number errorNumber if isAliasOfFolder then tell application "Finder" delete droppedItem end tell end if display dialog errStr error errStr number errorNumber end try end adding folder items to
2012-10-29 22:34
nice!(0)
コメント(4)
トラックバック(0)
こんばんは。
エイリアスかどうかの判定は、alias of (info for (item 1 of aliasList)) の真偽値を見るようにすれば、Finder の言語設定に依存しないでいけるんじゃないかと思います。
AppleScript 久しぶり過ぎ…。いまは他にも方法あるのかもしれませんが、とりあえず。
by モリヤン (2012-11-01 22:52)
コメントありがとうございます。
Apple Script初心者なので助かりました。そう言う言い回しがあるんですね。
ダイアログの中の文字列には、なにかいいローカライズの方法があるんでしょうか?
by decafish (2012-11-05 20:50)
info for は標準附属の拡張関数みたいなもので、スクリプト編集プログラム…じゃなかった AppleScriptエディタでは、ファイル>用語説明を開く...で、StandardAdditions.osax を開くとドキュメントが確認できます。
display dialog で表示する文字列のローカライズについては、AppleScriptエディタで書くようなスクリプトでは僕は聞いたことありません。Xcode で AppleScript を使ってスタンドアロンアプリを作るときには、他言語同様の方法があるんじゃないかと思いますが、詳しくは知りません。お役に立てませんー。すみませんー。
by モリヤン (2012-11-06 23:33)
詳しい解説までしていただいてお手数をおかけしました。理解しました。ありがとうございます。
やっぱりApple Scriptは古いMac OSのスタイルを引き継いでいるんでしょうか。
OS Xのバンドルによるローカライズのしくみは使う上では簡単でいいんですが、リソースフォークよりは少なくともシステムは難しいことをしているので、古いApple Scriptと馴染みがわるいということなのかしら。
by decafish (2012-11-07 21:01)