views:

952

answers:

5

Simply moving the file to ~/.Trash/ will not work, as if the file os on an external drive, it will move the file to the main system drive..

Also, there are other conditions, like files on external drives get moved to /Volumes/.Trash/501/ (or whatever the current user's ID is)

Given a file or folder path, what is the correct way to determine the trash folder? I imagine the language is pretty irrelevant, but I intend to use Python

+2  A: 

The File Manager API has a pair of functions called FSMoveObjectToTrashAsync and FSPathMoveObjectToTrashSync.

Not sure if that is exposed to Python or not.

Matthew Schinckel
+4  A: 

Alternatively, if you're on OS X 10.5, you could use Scripting Bridge to delete files via the Finder. I've done this in Ruby code here via RubyCocoa. The the gist of it is:

url = NSURL.fileURLWithPath(path)
finder = SBApplication.applicationWithBundleIdentifier("com.apple.Finder")
item = finder.items.objectAtLocation(url)
item.delete

You could easily do something similar with PyObjC.

Dave Dribin
Or appscript, I suspect.
Matthew Schinckel
+2  A: 

Based upon code from http://www.cocoadev.com/index.pl?MoveToTrash I have came up with the following:

def get_trash_path(input_file):
    path, file = os.path.split(input_file)
    if path.startswith("/Volumes/"):
        # /Volumes/driveName/.Trashes/<uid>
        s = path.split(os.path.sep)
        # s[2] is drive name ([0] is empty, [1] is Volumes)
        trash_path = os.path.join("/Volumes", s[2], ".Trashes", str(os.getuid()))
        if not os.path.isdir(trash_path):
            raise IOError("Volume appears to be a network drive (%s could not be found)" % (trash_path))
    else:
        trash_path = os.path.join(os.getenv("HOME"), ".Trash")
    return trash_path

Fairly basic, and there's a few things that have to be done seperatly, particularly checking if the filename already exist in trash (to avoid overwriting) and the actual moving to trash, but it seems to cover most things (internal, external and network drives)

Update: I wanted to trash a file in a Python script, so I re-implemented Dave Dribin's solution in Python:

from AppKit import NSURL
from ScriptingBridge import SBApplication

def trashPath(path):
    """Trashes a path using the Finder, via OS X's Scripting Bridge.
    """
    targetfile = NSURL.fileURLWithPath_(path)
    finder = SBApplication.applicationWithBundleIdentifier_("com.apple.Finder")
    items = finder.items().objectAtLocation_(targetfile)
    items.delete()

Usage is simple:

trashPath("/tmp/examplefile")
dbr
+2  A: 

A better way is NSWorkspaceRecycleOperation, which is one of the operations you can use with -[NSWorkspace performFileOperation:source:destination:files:tag:]. The constant's name is another artifact of Cocoa's NeXT heritage; its function is to move the item to the Trash.

Since it's part of Cocoa, it should be available to both Python and Ruby.

Peter Hosey
+1  A: 

Another one in ruby:

Appscript.app('Finder').items[MacTypes::Alias.path(path)].delete

You will need rb-appscript gem, you can read about it here

tig