Getting path of deleted item from Scripting Bridge SBObject in Swift

In the Swift function at the end of this post, I use Scripting Bridge to have Finder delete a path. The variable result is a SBObject returned by the delete() function. I know that result somehow contains the new path of the deleted item in the trash folder, but I don't know how to nicely extract it as a single String.

If I print(String(describing: result)), I get output like:

<SBObject @0x0123456789ab: <class 'appf'> "AppName.app" of <class 'cfol'> ".Trash" of <class 'cfol'> "user" of <class 'cfol'> "Users" of startupDisk of application "Finder" (822)>

Is there any way to obtain the String "/Users/user/.Trash/AppName.app" from result without having to perform string parsing on the above output?

The Finder* types in the code below are from https://github.com/tingraldi/SwiftScripting/blob/master/Frameworks/FinderScripting/FinderScripting/Finder.swift

func trash(path: String) throws {
    guard let finder: FinderApplication = SBApplication(bundleIdentifier: "com.apple.finder") else {
        throw runtimeError("Failed to obtain Finder access: com.apple.finder does not exist")
    }

    guard let items = finder.items else {
        throw runtimeError("Failed to obtain Finder access: finder.items does not exist")
    }

    let object = items().object(atLocation: URL(fileURLWithPath: path))

    guard let item = object as? FinderItem else {
        throw runtimeError(
            """
            Failed to obtain Finder access: finder.items().object(atLocation: URL(fileURLWithPath: \
            \"\(path)\") is a '\(type(of: object))' that does not conform to 'FinderItem'
            """
        )
    }

    guard let delete = item.delete else {
        throw runtimeError("Failed to obtain Finder access: FinderItem.delete does not exist")
    }

    let result = delete()
}
Answered by DTS Engineer in 811035022

Though it's not obvious from the generic type returned by delete, delete actually returns a FinderItem that contains an object specifier referring to the file in the trash. For example, put a file named "testfile.pdf" in your documents folder and try running this script in the Script Editor:

tell application "Finder"
	set target_file to document file "testfile.pdf" of item "Documents" of folder "dtsengineer42" of folder "Users" of startup disk of application "Finder"
	set new_location to delete target_file
	return new_location
end tell

returns: document file "testfile.pdf" of item ".Trash" of folder "dtsengineer42" of folder "Users" of startup disk of application "Finder"

*NOTE - these directions use my home folder name, you will need to change that to yours for them to work on your machine.

This is an object specifier specifying where the object is with directions for finding it. And, you can change this script to get the file url for the trashed file like so:

tell application "Finder"
	set target_file to document file "testfile.pdf" of item "Documents" of folder "dtsengineer42" of folder "Users" of startup disk of application "Finder"
	set new_location to delete target_file
	return URL of new_location
end tell

returns "file:///Users/dtsengineer42/.Trash/testfile.pdf"

And of course you can do the same thing with Scripting Bridge. But, in this case, the delete command returns a generic SBObject. Coerce the SBObject returned by delete into a FinderItem and then you can access the URL method and convert the object specifier into a URL like so:

    NSString *testFile = @"testfile.pdf";
    FinderFile *targetFile = [[[[[self.finder home] folders]
                                objectWithName:@"Documents"] files]
                              objectWithName: testFile];
    if ( [targetFile exists] ) {
        NSLog(@"%@ exists", testFile);
    } else {
        NSLog(@"%@ does not exist", testFile);
    }
    
    SBObject *movedTargetFile = [targetFile delete];
    NSString *theURL = [(FinderItem *) movedTargetFile URL];
    NSLog(@"moved target = %@", theURL);

outputs:

file exists
moved target = file:///Users/dtsengineer42/.Trash/testfile.pdf
Accepted Answer

Though it's not obvious from the generic type returned by delete, delete actually returns a FinderItem that contains an object specifier referring to the file in the trash. For example, put a file named "testfile.pdf" in your documents folder and try running this script in the Script Editor:

tell application "Finder"
	set target_file to document file "testfile.pdf" of item "Documents" of folder "dtsengineer42" of folder "Users" of startup disk of application "Finder"
	set new_location to delete target_file
	return new_location
end tell

returns: document file "testfile.pdf" of item ".Trash" of folder "dtsengineer42" of folder "Users" of startup disk of application "Finder"

*NOTE - these directions use my home folder name, you will need to change that to yours for them to work on your machine.

This is an object specifier specifying where the object is with directions for finding it. And, you can change this script to get the file url for the trashed file like so:

tell application "Finder"
	set target_file to document file "testfile.pdf" of item "Documents" of folder "dtsengineer42" of folder "Users" of startup disk of application "Finder"
	set new_location to delete target_file
	return URL of new_location
end tell

returns "file:///Users/dtsengineer42/.Trash/testfile.pdf"

And of course you can do the same thing with Scripting Bridge. But, in this case, the delete command returns a generic SBObject. Coerce the SBObject returned by delete into a FinderItem and then you can access the URL method and convert the object specifier into a URL like so:

    NSString *testFile = @"testfile.pdf";
    FinderFile *targetFile = [[[[[self.finder home] folders]
                                objectWithName:@"Documents"] files]
                              objectWithName: testFile];
    if ( [targetFile exists] ) {
        NSLog(@"%@ exists", testFile);
    } else {
        NSLog(@"%@ does not exist", testFile);
    }
    
    SBObject *movedTargetFile = [targetFile delete];
    NSString *theURL = [(FinderItem *) movedTargetFile URL];
    NSLog(@"moved target = %@", theURL);

outputs:

file exists
moved target = file:///Users/dtsengineer42/.Trash/testfile.pdf

I know that I earlier tried casting to FinderItem then accessing the URL property, but that it didn't work, either because it said that URL didn't exist, or because it was nil or "". I might have done that in the Xcode debugger rather than in code.

Whatever it was, your solution worked. I have no idea why it didn't work for me when I tried it earlier.

Thanks.

Getting path of deleted item from Scripting Bridge SBObject in Swift
 
 
Q