1
0
Fork 0
dotfiles/.local/bin/trash-restore

82 lines
2.0 KiB
Perl
Executable File

#!/bin/perl
use strict;
use warnings;
use feature("signatures");
use File::Basename;
use File::Copy;
use Cwd;
sub fs_root($file_name) {
chomp(my $ret = `stat -c %m $file_name`);
return $ret;
}
sub trash_dir($file_fs_root) {
my $data_path = "$ENV{'XDG_DATA_HOME'}" // "$ENV{'HOME'}/.local/share";
return "$data_path/Trash/" if ($file_fs_root eq fs_root($data_path));
return "$file_fs_root/.Trash/";
}
sub trashed_files($search_path, $trash_path) {
my @ret;
opendir(my $dir, "$trash_path/info") or die "$!\n";
for (readdir $dir) {
$_ =~ /\.~\d~$/ or next;
open(FH, "<", "$trash_path/info/$_") or next;
<FH> eq "[Trash Info]\n" or next;
my ($name, $path, $suffix) = fileparse((<FH> =~ /(?<=Path=)(.+)$/)[0]);
$path =~ /^$search_path\/?$/ or next;
my $deletion_date = (<FH> =~ /(?<=DeletionDate=)(.+)$/)[0];
chomp($deletion_date = `date -d ${deletion_date} +'%x %X'`);
push(@ret, [$path, "${name}${suffix}", $deletion_date, $_]);
}
return @ret;
}
sub fzf_files(@files) {
my $n = 0;
my $str;
for my $e (@files) {
$str .= "\n" if $n > 0;
$str .= "$n | $$e[2] | $$e[1]";
$n++;
}
chomp($str);
my $sel =`echo '$str' | fzf`;
!$sel and exit;
my $index = substr($sel, 0, index($sel, ' '));
return $index;
}
# NOTE: Execution starts here
#
my $target_directory;
if ($#ARGV + 1 > 1) {
die "Bad Arguments\n";
} elsif ($#ARGV + 1 == 1) {
$target_directory = shift;
chomp($target_directory = `realpath -s $target_directory`);
stat $target_directory or die "$!\n";
} else {
$target_directory = getcwd();
}
my $trash_dir = trash_dir(fs_root($target_directory));
my @files = trashed_files($target_directory, $trash_dir);
!@files and exit;
my $index = fzf_files(@files);
my $file_dest = $files[$index][0] . $files[$index][1];
my $file_src = $trash_dir . "files/" . $files[$index][3];
my $file_info = $trash_dir . "info/" . $files[$index][3];
move($file_src, $file_dest) or die "$!\n";
unlink($file_info);