sindresorhus / macos-trash

Move files and folders to the trash
MIT License
377 stars 14 forks source link

`Put back` only works for the first file #4

Open sindresorhus opened 9 years ago

sindresorhus commented 9 years ago

Continued from https://github.com/sindresorhus/trash/issues/24. This is a really weird issue.

Only the first file trashed with trashItemAtURL in a process will have the ability to Put back from the trash. I've narrowed down the code and the below still only adds Put back for the first file foo:

@import Foundation;

int main() {
    [[[NSFileManager alloc] init] trashItemAtURL:[NSURL URLWithString:@"file:///Users/sindresorhus/dev/osx-trash/foo"] resultingItemURL:nil error:nil];
    [[[NSFileManager alloc] init] trashItemAtURL:[NSURL URLWithString:@"file:///Users/sindresorhus/dev/osx-trash/bar"] resultingItemURL:nil error:nil];

    return 0;
}

I'm starting to think this is a OS X bug. Would appriciate being proved wrong, though. Gonna open an issue on radar when I get a chance, unless someone can figure this out.

SamVerschueren commented 9 years ago

This is what I found out at StackOverflow:

http://stackoverflow.com/a/27847797

Let's try to pass an NSURL to resultingItemURL.

sindresorhus commented 9 years ago

Yeah, I've tried that too and lots of other things. Nothing. Debugged this for hours...

SamVerschueren commented 9 years ago

Have you tried adding a sleep between two consecutive calls? Maybe something in the background can't follow the trash procedure and gets confused...

sindresorhus commented 9 years ago

Yup, also tried doing some other NSFileManager between, and also tried making the calls in different threads.

sindresorhus commented 9 years ago

@pornel Sorry for mentioning you, but you're the only the Obj-C person I know of. Any idea what's going on?

thomassnielsen commented 9 years ago

Any particular reason why you allocate two file managers instead of using the same instance? (Not sure if it affects the problem, but worth trying).

sindresorhus commented 9 years ago

@thomassnielsen Just to make sure the problem is not with reusing the defaultManager. That's not the problem, though.

sindresorhus commented 9 years ago

@fcanas: After a deep 🐇 hole: Looks like a NSFileManager 🐛. Can workaround by having Finder delete via ScriptingBridge. - https://twitter.com/fcanas/status/654817376790167552

Qix- commented 9 years ago

Deleting via scriptingbridge is... messy. Let my try to repro and play with it a bit.


I can't even repro it working for the first file; nothing can be put back. Calling trash with a single file doesn't even work. Confirmed it's not even the directory that matters; it's any directory.

I tried figuring out where it's storing the original location of the file, but I can't find a PList or anything.

Qix- commented 9 years ago

The answer seems to lay within the .DS_Store file (~/.Trash/.DS_Store). Legend has it Apple has deprecated their use, but it seems to be the key here.

$ pwd
/src/sindresorhus.osx-trash
$ touch foo bar
$ <use finder to manually Move To Trash `foo`>
$ ./trash bar
$ xxd ~/.Trash/.DS_Store
. . . snip . . .
00001570: 0069 006e 0064 0072 0065 0073 006f 0072  .i.n.d.r.e.s.o.r
00001580: 0068 0075 0073 002e 006f 0073 0078 002d  .h.u.s...o.s.x.-
00001590: 0074 0072 0061 0073 0068 002f 0000 0003  .t.r.a.s.h./....
000015a0: 0066 006f 006f 7074 624e 7573 7472 0000  .f.o.optbNustr..
000015b0: 0003 0066 006f 006f 0000 0026 0047 006f  ...f.o.o
. . . snip . . .

ptbNustr is some sort of separator token

Upon further look, as I suspected, bar was nowhere to be seen in the .DS_Store, which means Trash doesn't know where the file came from; this is definitely a bug in [NSFileManager trashItemAtURL: resultingItemURL:error:]. Our workaround could be to edit the .DS_Store file manually, though there isn't a cocoa interface to do this; we'd have to manually do it ourselves.

Qix- commented 9 years ago

I filed a bug with Apple; bug 23153124. Don't think it's publicly viewable. I'll update here as I hear anything.

Probably want to work on a workaround for now.

sindresorhus commented 9 years ago

Oh, very interesting. Thanks for looking into this @Qix- and for filing the bug. Would you mind also filing it on https://openradar.appspot.com and pasting a link to it here?

Qix- commented 9 years ago

Will do; also, it looks like Put Back isn't the most polished feature to begin with.


Opened radar rdar://23153124.

Qix- commented 9 years ago

@gchriswill Why not Objective-C? ;)

As well, @sindresorhus has been doing a bit of C lately, not just for OS X. That's probably why.

sindresorhus commented 9 years ago

I initally wrote this in Swift, but had to rewrite it in Objective-C as the binary was several megabytes (because before Swift 2 the whole interpreter was embedded in the binary). Doesn't really matter anyways, though, as it's so little code.

kornelski commented 9 years ago

@sindresorhus Sorry I couldn't check that earlier. ImageOptim suffers from the same problem, and I'm pretty sure Put Back used to work for all files when I first wrote it, so it's a regression in OS X.

kornelski commented 9 years ago

sleep(10) between the calls "fixes" it, so there may be some kind of delayed flush in Finder. The problem still happens when I try to delete 1 file per process, by launching 2 processes, so it's a system-wide bug, not something limited to NSFileManager instance.

Qix- commented 9 years ago

@pornel could you write a quick POC for that? I'll add it to the bug report.

kornelski commented 9 years ago

The code at the top of the thread already shows the bug very well.

Qix- commented 9 years ago

@pornel with the sleep() call I mean.

sindresorhus commented 9 years ago

@pornel Oh, interesting. Thanks for chiming in.

sleep(2); is the shortest sleep that makes it work for me. sleep(1) and [NSThread sleepForTimeInterval:1.9] does not. So it seems there some kind of flush after 2 seconds.

sindresorhus commented 8 years ago

Still an issue in macOS Sierra...

Qix- commented 8 years ago

Let me check on the radar...

EDIT: Nothing. I've added information re: Sierra.

Qix- commented 8 years ago

Should we resort to creating a .DS_Store editor? There's a Perl implementation that we could port.

Qix- commented 7 years ago

Still nothing on the radar.

IngmarStein commented 7 years ago

I just stumbled upon this while debugging https://github.com/IngmarStein/Monolingual/ which suffers from the same bug. Thanks for your analysis and please keep us in the loop when (or if) the radar status changes.

denrat commented 7 years ago

There's a Swift implementation of this function, maybe that has better chance of working on Sierra?

sindresorhus commented 7 years ago

@h0d I doubt that will make any difference. That Swift call uses the same Objective-C API underneath.

Qix- commented 7 years ago

^ Correct.

leanne63 commented 6 years ago

Still having problem in 10.13.5. No "Put back" option appears on deleted files in Trash. Any news?

Qix- commented 6 years ago

Thanks for the reminder @leanne63 - just checked bugreport.apple.com on the radar (23153124) and they have not responded in almost three years (Oct 16, 2015). There's not even an assigned status.

I added another comment requesting a response, but don't hold your breath.

FWIW, I've filed two other issues through Apple's bug report system and both received responses rather quickly. Not sure why this one is falling through the cracks.

Feel free to ping me again in another year :trollface:

sindresorhus commented 6 years ago

I've reproduced it in macOS 10.14 beta 3 too and I've filed a duplicate radar: https://openradar.appspot.com/radar?id=5063396789583872

jjarava commented 5 years ago

I'm testing trash and "Put Back" is not an option, even if you delete just one file

Using Finder to delete the file is how other utils have worked around this issue (though not elegant, I agree)... but it seems to have some side issues on files on networked shares that you've side-stepped (see https://github.com/ali-rantakari/trash/issues/32)

jjarava commented 5 years ago

Testing a similar utility (https://github.com/sindresorhus/macos-trash), they implement an elegant workaround for the Networked/mapped folder issue:

When trying to delete a file on an network share, the utility fails with a message that the volume doesn't have a Trash folder:

jjarava$ trash-swift Safari\ -\ 6\ feb\ 2018\ 22\:35\ copy.pdf
“Safari - 6 feb 2018 22/35 copy.pdf” couldn’t be moved to the trash because the volume “DRIVE” doesn’t have one

(trash-swift is the name I've given to the binary complied from https://github.com/sindresorhus/macos-trash on my system)

Qix- commented 5 years ago

Just as an FYI I lost access to the original report, so I cannot check/update the original radar. @sindresorhus's radar should serve as most up-to-date version.

tjx666 commented 2 years ago

any progress?

Qix- commented 2 years ago

@tjx666

image

gingerbeardman commented 2 years ago

This shell script works with full Put Back support.

https://github.com/morgant/tools-osx/blob/master/src/trash

forivall commented 2 years ago

Also, ali-rantakari/trash with the -F flag works with full put-back support.