AppleScriptでゴミ箱モドキを作った

Macのデスクトップからゴミ箱がなくなって久しい上に、唯一の代替手段であったDragThingも動かなくなって久しい昨今、それでもデスクトップにゴミ箱が欲しいんです。モドキで良いからAppleScriptで作ります。

昔、Macのデスクトップにはゴミ箱があり、不要なファイルのゴミ箱として、あるいはボリュームのイジェクト装置として使われていました。

 

MacOSXになってデスクトップからゴミ箱はなくなりましたが、DragThingが引き継ぎました。しかし DragThing が使えるのは macOS10.14 mojave まで。

DragThingのゴミ箱
DragThingのゴミ箱

今ではデスクトップにゴミ箱があったことすら知らない人が大半で、この機能を欲する人そのものがいなくなりました。

ゴミ箱を作る

デスクトップに置くゴミ箱の代替アプリはありません。DragThing のゴミ箱を引き継ぐアプリもありません。ゴミ箱が必要な人もこの世にいません。自分を除いて。ならば作るしかありません。

この後、解説と試作を経て、このページの最後に完成したAppleScriptを載せております。

ゴミ箱の機能

お手本となる本来のゴミ箱は次の機能を持ちます。

  • ファイルやフォルダをドラッグすれば各ボリュームのゴミ箱に入れられる
  • イジェクト可能なボリュームをドラッグすればイジェクトされる
  • ゴミ箱が空の時とファイルやフォルダが入っている時でゴミ箱アイコンが変化する
  • ボリュームをクリック・ホールドしたらアイコンがイジェクトに変わる

このうち、上の二つは簡単に実現できます。アイコンの変化は、難しいことが出来る天才プログラマーなら作れるかもしれませんが普通の人には無理です。

Automator かんたんゴミ箱

さてファイルのゴミ箱機能とイジェクト機能、それぞれ別個なら Automator ですぐに作れます。

ゴミ箱

Automator: Finder項目をゴミ箱に入れる
Automator: Finder項目をゴミ箱に入れる

「Finder項目をゴミ箱に入れる」が用意されているのでそれを持ってくるだけです。

イジェクト

 

Automator: ディスクと取り出す
Automator: ディスクを取り出す

「ディスクを取り出す」が用意されているのでそれを持ってくるだけです。

アプリケーションとして保存

これらをアプリケーションとして保存したりフォルダアクションにセットしたりします。あとはそれっぽいアイコンを付ければ一撃で完成ですね。

一般人に出来るのはこの程度なので、二つのゴミ箱をデスクトップに置いて、機嫌良く使っていました。

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というのを定義してボリュームのリストから判断させているようです。

これをアプリケーションとして保存してデスクトップに置き、それらしいアイコンを付ければ完成。

eject icon trach icon ゴミ箱とイジェクトアイコン

ファイルかフォルダをドラッグすればゴミ箱に入り、イジェクト可能なボリュームをドラッグすればイジェクトされます。

アイコンの変化はないので、ゴミ箱アイコンにするかイジェクトアイコンにするか悩ましいところですが、挙動は期待通りでした。

app化したファイル
アイコンは後で考えよう

 

これでしばらく機嫌良く使っていましたが、まだまだ欲が出てきます。このアプリはドラッグ専用なので、ダブルクリックしても何も起こりません。

ダブルクリックならゴミ箱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


これをスクリプトエディタに書いてアプリケーションとして書き出せば自作ゴミ箱の完成。

ダブルクリックすればゴミ箱が開き
ボリュームをドラッグすればイジェクトされ
ファイルやフォルダをドラッグすればゴミ箱に入ります。

アイコンが変化しないことを除けば、理想の挙動となりました。

とりあえず妙なアイコンをつけてデスクトップに置いておきます。

trash eject icon

 

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

This site uses Akismet to reduce spam. Learn how your comment data is processed.