Skip to content

Instantly share code, notes, and snippets.

@khalman-m
Forked from cpq/restore_mac_trash.pl
Last active April 13, 2020 01:26
Show Gist options
  • Star 20 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save khalman-m/8ccc248963bb65df2214 to your computer and use it in GitHub Desktop.
Save khalman-m/8ccc248963bb65df2214 to your computer and use it in GitHub Desktop.
#!/usr/bin/env perl
# Copyright (c) 2015 Sergey Lyubka
# All rights reserved
use Encode;
my $dir = "/Users/$ENV{USER}/.Trash";
sub read_file($) { local $/; open FD, $_[0] or die $_[0]; binmode FD; <FD>; }
sub u32($$) { unpack('N', substr($_[0], $_[1], 4)) }
sub str($$$) { my $s = substr($_[0], $_[1], $_[2]); Encode::from_to($s,'UCS-2BE','utf8'); $s; }
sub read_block($$) {
my ($p, $o) = @_;
my $cnt = u32($p, $o + 8);
$o += 12;
while ($cnt--) {
my $name_len = u32($p, $o) * 2;
my $name = str($p, $o + 4, $name_len);
my $tag = substr($p, $o + 4 + $name_len, 4);
my $type = substr($p, $o + 8 + $name_len, 4);
print "[$o] [$name] [$name_len] [$tag] [$type]\n";
$o += $name_len + 12;
if ($type eq 'bool') { $o += 1 }
elsif ($type =~ /shor|long|type/) { $o += 4; }
elsif ($type =~ /comp|dutc/) { $o += 8; }
elsif ($type eq 'ustr') {
my $n = 2 * u32($p, $o);
if ($tag eq 'ptbL') {
my $original_location = str($p, $o + 4, $n);
my $cmd0 = "mkdir -p \"/$original_location\"";
my $cmd = "mv \"$dir/$name\" \"/$original_location\"";
print "$cmd0\n";
print "$cmd\n";
system($cmd0);
system($cmd);
}
$o += $n + 4;
}
elsif ($type eq 'blob') { $o += u32($p, $o) + 4; }
else { last; }
}
return $cnt;
}
my $store = read_file("$dir/.DS_Store");
my $off = u32($store, 0x14) & ~15;
while (1) {
last if read_block($store, $off) == 0;
$off = ($off & 0xfffff000) + 0x1000;
};
@jonyoi
Copy link

jonyoi commented Nov 23, 2016

this script saved me hours. Thanks, man you guys are genius. Maybe one day I can code like you guys.

@okayama1
Copy link

okayama1 commented Dec 1, 2016

Hi , I am trying to recover lots of files from the trash that I deleted by mistake (the folders and nested folders did not get deleted. It has been only the files). I have tried to run the function through the console but what has happened is that my files ended up having a change in the names and they are still in the Trash. An example:

weekend9 11.08.53 AM 11.08.53 AM.md and before it was called weeekend9.md

I am using El Capitan version OS and I actually don't know anything about Pearl (probably I am doing something wrong but I don't know what it is) so any help with this would be highly appreciate it. When I run the function I get the message Directory not empty. Thanks a lot.

@galvarez3d
Copy link

I´ also getting a similar error. Mine are actually moved to their original location but a file originally called "NAME" gets restored as "NAME 16.27.17 16.27.17.log"
Maybe the structure of .DS_Store is modified by other parameters such as language (mine is in spanish) or OS date format...? so the character count (I think this is what the script is based upon) is not always accurate?

@ed8888new
Copy link

Hi, it's very good script. Thank you very much.

Copy link

ghost commented Jun 17, 2017

How long does this take to run on average?

@cmicat
Copy link

cmicat commented Oct 10, 2017

I have such error
mv: cannot stat '/Users/cmicat/.Trash/weedfs_0.70_darwin_amd64.zip': No such file or directory
Anyone know how to check if file exists before move?

@afshinrahimi
Copy link

million thanks, saved me hours!

@drKreso
Copy link

drKreso commented May 27, 2019

thanks!

@shurekek19
Copy link

Sir please help me. Where can i input this codes thank you so much

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