Macのデスクトップからゴミ箱がなくなって久しい上に、唯一の代替手段であったDragThingも動かなくなって久しい昨今、それでもデスクトップにゴミ箱が欲しいんです。モドキで良いからAppleScriptで作ります。
昔、Macのデスクトップにはゴミ箱があり、不要なファイルのゴミ箱として、あるいはボリュームのイジェクト装置として使われていました。
MacOSXになってデスクトップからゴミ箱はなくなりましたが、DragThingが引き継ぎました。しかし DragThing が使えるのは macOS10.14 mojave まで。
今ではデスクトップにゴミ箱があったことすら知らない人が大半で、この機能を欲する人そのものがいなくなりました。
ゴミ箱を作る
デスクトップに置くゴミ箱の代替アプリはありません。DragThing のゴミ箱を引き継ぐアプリもありません。ゴミ箱が必要な人もこの世にいません。自分を除いて。ならば作るしかありません。
この後、解説と試作を経て、このページの最後に完成したAppleScriptを載せております。
ゴミ箱の機能
お手本となる本来のゴミ箱は次の機能を持ちます。
- ファイルやフォルダをドラッグすれば各ボリュームのゴミ箱に入れられる
- イジェクト可能なボリュームをドラッグすればイジェクトされる
- ゴミ箱が空の時とファイルやフォルダが入っている時でゴミ箱アイコンが変化する
- ボリュームをクリック・ホールドしたらアイコンがイジェクトに変わる
このうち、上の二つは簡単に実現できます。アイコンの変化は、難しいことが出来る天才プログラマーなら作れるかもしれませんが普通の人には無理です。
Automator かんたんゴミ箱
さてファイルのゴミ箱機能とイジェクト機能、それぞれ別個なら Automator ですぐに作れます。
ゴミ箱とイジェクト
「Finder項目をゴミ箱に入れる」と「ディスクを取り出す」が用意されているのでそれを持ってくるだけです。
アプリケーションとして保存
これらをアプリケーションとして保存したりフォルダアクションにセットしたりします。あとはそれっぽいアイコンを付ければ一撃で完成ですね。
一般人に出来るのはこの程度なので、二つのゴミ箱をデスクトップに置いて、機嫌良く使っていました。
IF で分岐させる
しかし欲が出てきます。二つの機能を1個にまとめたい。1個にするには難しいことをクリアしないといけません。
一つは、IF で処理を分岐させることです。項目がファイルやフォルダならゴミ箱、ドライブならイジェクトと。
もう一つは、分岐条件です。ボリュームってどうやって判断するんでしょう。ネットワークボリュームやディスクイメージからマウントしたボリュームもイジェクト仲間に加えたいし。どう書けば良いのか見当もつきません。
Automator は IF が使えないので、AppleScript かシェルスクリプトのコードを書かねばなりません。
AppleScript で作るゴミ箱
面倒がないのはAppleScriptですのでそれでやってみましょう。
ドラッグすればゴミ箱またはイジェクト
ドラッグしたアイテムがファイルやフォルダならゴミ箱、ボリュームならイジェクトになるスクリプトをぜひ書きたい。でもAppleScriptぜんぜん判らないので誰かに尋ねましょうか。
「もしもし。こんにちは」
「はいはい。どうしました?」
「項目が “イジェクト可能なボリュームなら” って条件、どう書けばいい?その結果に応じてイジェクトさせたりゴミ箱に移動させたりしたいんですけど」
「ボリュームかどうかを確認して、あとはエラー込みで実際にイジェクトを試みればいいのでは」
「AppleScript全然わからないので、コードを書いてみてくれませんか?」
「お安いご用です」
というわけで書いて貰ったのが以下です。
-- ドラッグ&ドロップされたアイテムを取得 on open these_items repeat with anItem in these_items -- アイテムのパスを取得 set itemPath to POSIX path of (anItem as text) -- アイテムがボリュームかどうかを確認 if isVolume(itemPath) then try -- ボリュームをイジェクト do shell script "diskutil eject " & quoted form of itemPath on error errMsg display dialog "Error ejecting volume: " & errMsg end try else -- ファイルまたはフォルダをゴミ箱に移動 try tell application "Finder" move (POSIX file itemPath as alias) to the trash end tell on error errMsg display dialog "Error moving item to trash: " & errMsg end try end if end repeat end open -- アイテムがボリュームかどうかを確認するハンドラー on isVolume(itemPath) try -- POSIXパスからディスクボリュームのリストを取得 set diskList to do shell script "diskutil list | grep " & quoted form of (do shell script "basename " & quoted form of itemPath) -- 出力にアイテムが含まれていれば、ボリュームとして扱う return diskList is not "" on error return false end try end isVolume
ボリュームかどうかを判断するのが意外と手間なのですね。isVolumeというのを定義してボリュームのリストから判断させているようです。
これをアプリケーションとして保存してデスクトップに置き、それらしいアイコンを付ければ完成。
ファイルかフォルダをドラッグすればゴミ箱に入り、イジェクト可能なボリュームをドラッグすればイジェクトされます。
アイコンの変化はないので、ゴミ箱アイコンにするかイジェクトアイコンにするか悩ましいところですが、挙動は期待通りでした。
これでしばらく機嫌良く使っていましたが、まだまだ欲が出てきます。このアプリはドラッグ専用なので、ダブルクリックしても何も起こりません。
ダブルクリックならゴミ箱Open、ドラッグならゴミ箱かイジェクト
ダブルクリックした場合はゴミ箱を開き、ドラッグなら先ほどの「ゴミ箱またはイジェクト」にしたいですよね。
以前なら数日間呻り倒して独学していたところですが、今は甘い先生がすぐそこにいます。
「もしもし。こんにちは」
「はいはい。どうしました」
「ダブルクリックならゴミ箱を開いて、アイテムドラッグならこの前のスクリプトが発動するようにするにはどう書けばいい?」
「複数のハンドラを用意して操作に応じた処理をすればいいさー」
「ええと・・・」
「on open でドラッグドロップされたアイテム処理、on run でアプリ起動の処理を分けるさー」
【完成品】
-- ドラッグ&ドロップされたアイテムを取得 on open these_items repeat with anItem in these_items -- アイテムのパスを取得 set itemPath to POSIX path of (anItem as text) -- アイテムがボリュームかどうかを確認 if isVolume(itemPath) then try -- ボリュームをイジェクト do shell script "diskutil eject " & quoted form of itemPath on error errMsg display dialog "Error ejecting volume: " & errMsg end try else -- ファイルまたはフォルダをゴミ箱に移動 try tell application "Finder" move (POSIX file itemPath as alias) to the trash end tell on error errMsg display dialog "Error moving item to trash: " & errMsg end try end if end repeat end open -- アプリケーションが起動したときの処理 on run try -- ゴミ箱を開く tell application "Finder" open the trash end tell on error errMsg display dialog "Error opening trash: " & errMsg end try end run -- アイテムがボリュームかどうかを確認するハンドラー on isVolume(itemPath) try -- POSIXパスからディスクボリュームのリストを取得 set diskList to do shell script "diskutil list | grep " & quoted form of (do shell script "basename " & quoted form of itemPath) -- 出力にアイテムが含まれていれば、ボリュームとして扱う return diskList is not "" on error return false end try end isVolume
これをスクリプトエディタに書いてアプリケーションとして書き出せば自作ゴミ箱の完成。
ダブルクリックすればゴミ箱が開き
ボリュームをドラッグすればイジェクトされ
ファイルやフォルダをドラッグすればゴミ箱に入ります。
アイコンが変化しないことを除けば、理想の挙動となりました。
とりあえず妙なアイコンをつけてデスクトップに置いておきます。