Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Put back only works for the first file #4

Open
sindresorhus opened this issue Oct 15, 2015 · 39 comments
Open

Put back only works for the first file #4

sindresorhus opened this issue Oct 15, 2015 · 39 comments

Comments

@sindresorhus
Copy link
Owner

Continued from sindresorhus/trash#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
Copy link

This is what I found out at StackOverflow:

http://stackoverflow.com/a/27847797

Let's try to pass an NSURL to resultingItemURL.

@sindresorhus
Copy link
Owner Author

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

@SamVerschueren
Copy link

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
Copy link
Owner Author

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

@sindresorhus
Copy link
Owner Author

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

@thomassnielsen
Copy link

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
Copy link
Owner Author

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

@sindresorhus
Copy link
Owner Author

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

@Qix-
Copy link

Qix- commented Oct 16, 2015

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-
Copy link

Qix- commented Oct 16, 2015

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-
Copy link

Qix- commented Oct 16, 2015

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
Copy link
Owner Author

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-
Copy link

Qix- commented Oct 17, 2015

@Qix-
Copy link

Qix- commented Oct 22, 2015

@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
Copy link
Owner Author

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
Copy link

@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
Copy link

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-
Copy link

Qix- commented Oct 23, 2015

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

@kornelski
Copy link

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

@Qix-
Copy link

Qix- commented Oct 23, 2015

@pornel with the sleep() call I mean.

@sindresorhus
Copy link
Owner Author

@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
Copy link
Owner Author

Still an issue in macOS Sierra...

@Qix-
Copy link

Qix- commented Sep 22, 2016

Let me check on the radar...

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

@Qix-
Copy link

Qix- commented Sep 22, 2016

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

@Qix-
Copy link

Qix- commented Feb 5, 2017

Still nothing on the radar.

@IngmarStein
Copy link

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
Copy link

denrat commented Apr 24, 2017

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

@sindresorhus
Copy link
Owner Author

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

@Qix-
Copy link

Qix- commented Apr 24, 2017

^ Correct.

@leanne63
Copy link

leanne63 commented Jul 5, 2018

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

@Qix-
Copy link

Qix- commented Jul 5, 2018

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
Copy link
Owner Author

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
Copy link

jjarava commented May 28, 2019

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 ali-rantakari/trash#32)

@jjarava
Copy link

jjarava commented May 28, 2019

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-
Copy link

Qix- commented May 28, 2019

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
Copy link

tjx666 commented Jan 14, 2022

any progress?

@Qix-
Copy link

Qix- commented Jan 14, 2022

@tjx666

image

@gingerbeardman
Copy link
Contributor

This shell script works with full Put Back support.

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

@forivall
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests