読者です 読者をやめる 読者になる 読者になる

その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

rmコマンドを「ゴミ箱」の移動にした挙げ句、undoを可能にするスクリプト書きました

(2012/1/7 追記)この記事のプログラムには色々問題があったので、それを改訂したものがこちらにございます。そちらをご覧下さい。

あけました。ご機嫌如何でしょうか。


さて。
rmコマンドを使用すると、対象となったファイルは即座に電子的あの世へと運ばれてしまいます。
"$ rm * "と打ち込んで「ギャッ!」となった経験がおありの方ならば、
「ゴミ箱というワンクッションがあれば……」と思った事があるのでは無いでしょうか。


という訳でゴミ箱を実装しました。
単純に、rmコマンド打ち込んだら"$ mv hoge ~/.Trash/ "みたいな感じで
".Trash"というゴミ箱ディレクトリにファイルを移動させるようなシェルスクリプト
書けば良かったんでしょうが、なんだか上手く行かなかったのでperlで書きました。
でもって、直前にrmしたファイルを元の位置に戻すスクリプトundoも書きました。


注 : 多分Unix/Linuxでしか動かないと思います。
   「Windowsで使いたい!」という謎の欲望が目覚めた場合は、いくらかの改造が必要だと思われます。


実行例を示しますと、こんな感じです。

$ rm A    #ファイルAがゴミ箱ディレクトリに移動
$ rm B    #ファイルBがゴミ箱ディレクトリに移動
$ rm C    #ファイルCがゴミ箱ディレクトリに移動
$ undo    #ファイルCが元の場所に戻る
$ undo    #ファイルBが元の位置に戻る
$ undo    #ファイルAが元の位置に戻る


以下ソースコードです

gotoTrash

対象とするファイルをゴミ箱ディレクトリに移動するスクリプト

#! /usr/bin/perl

use 5.010;
use Cwd;

#以下に記述されている「ゴミ箱のディレクトリ」には、
#任意の場所に自分で作った「ゴミ箱ディレクトリ」のパスを
#記述してください。
#e.g. : "/home/owner/.Trash"
my $trashDirectoryPath = "ゴミ箱のディレクトリ";

if( scalar @ARGV == 0 ){
    exit;
}

my @fileName;
foreach( @ARGV ){
    unless( /\s*-+\w+\b/g ){
        push( @fileName, $_ );
    }
}

if( scalar @fileName == 0 ){
    exit;
}

my @existFileName;
foreach( @fileName ){
    if( -e $_ ){
        push( @existFileName, $_ );
    }else{
        warn "$_ : No such file or directory\n"
    }
}

if( scalar @existFileName == 0 ){
    exit;
}

my ( $sec, $min, $hour, $day, $mon, 
     $year, $wday, $yday, $isdst ) = localtime(time);
$year += 1900;
$mon += 1;
my $timeStamp = sprintf "%4d%02d%02d%02d%02d%02d",
                        $year, $mon, $day, $hour, $min, $sec;

my $currentDirectoryPath =  getcwd();

#ゴミ箱ディレクトリの下に、タイムスタンプがディレクトリ名となっているディレクトリを作る
#e.g. : /home/owner/.Trash/YYYYMMDDhhmmss
$trashDirectoryPath .= $timeStamp;
mkdir "$trashDirectoryPath", 0755 or die "Cannot make directory: $!";

$trashDirectoryPath .= "/";
my $pathFile = $trashDirectoryPath . ".PATH";
unless( open OUT, " >$pathFile" ){
    die "Cannot create PATH file : $!\n";
}
print OUT $currentDirectoryPath . "\n";
close OUT;

foreach( @existFileName ){
    rename $_, $trashDirectoryPath.$_;
}

foreach( @existFileName ){
    say "$_ -> $trashDirectoryPath";
}

注 : CPANからcwdモジュールをインストールする必要があるのではないでしょうか。
注 : ファイルの移動と同時に作成される.PATHファイルは削除しないで下さい。
   下記のスクリプトundoが上手く働かなくなります。

undo

直前にゴミ箱へと移動したファイルを、元の位置に戻すスクリプト

#! /usr/bin/perl

use 5.010;
use File::Path;

#以下に記述されている「ゴミ箱のディレクトリ」には、
#任意の場所に自分で作った「ゴミ箱ディレクトリ」のパスを
#記述してください。
#e.g. : "/home/owner/.Trash"
my $trashDirectory = "ゴミ箱のディレクトリ";

my @directoryList = glob $trashDirectory."*";
if( scalar @directoryList == 0 ){
    exit;
}
foreach ( @directoryList ){
    s#^$trashDirectory##;    
}

my @sortedDirectoryList = sort @directoryList;
my $targetDirectory = $sortedDirectoryList[-1];
$targetDirectory = $trashDirectory . $targetDirectory;

my $pathFileLocation = " <".$targetDirectory."/.PATH";
unless( open PATH, $pathFileLocation ){
    die "Cannot open .PATH file: $!\n";
}
my $targetUndoLocation;
while( <PATH> ){
    chomp;
    $targetUndoLocation = $_;
}
close PATH;

my @targetUndoLocationList = split /\//, $targetUndoLocation;
shift @targetUndoLocationList;  #Remove null element
my $directoryTest;
foreach( @targetUndoLocationList ){
    $directoryTest .= "/" . $_;
    unless( -e $directoryTest ){
        mkdir "$directoryTest", 0755 or die "Cannot make directory: $!"; 
    }
}

unlink $targetDirectory."/.PATH";

my @targetUndoFileList = glob $targetDirectory."/*";
my $targetUndoFile;
foreach( @targetUndoFileList ){
    $targetUndoFile = $_;
    s#^$targetDirectory/##;
    rename $targetUndoFile, $targetUndoLocation."/".$_;
}

rmtree $targetDirectory;

say "Undo : $targetUndoFile -> $targetUndoLocation/";

注 : CPANからFile::Pathモジュールをインストールする必要があります。

cleanTrash

いわゆる「ゴミ箱を空にする」スクリプト

#! /usr/bin/perl

use 5.010;
use File::Path;

#以下に記述されている「ゴミ箱のディレクトリ」には、
#任意の場所に自分で作った「ゴミ箱ディレクトリ」のパスを
#記述してください。
#e.g. : "/home/owner/.Trash"
my $trashDirectory = "ゴミ箱のディレクトリ";

my @trashDirectoryList = glob $trashDirectory."*";
foreach( @trashDirectoryList ){
    rmtree $_;
}

注 : CPANからFile::Pathモジュールをインストールする必要があります。

あとは

$ chmod 755 [scriptName]
あたりで実行可能にしておいて、
.bashrcか何かに、
alias [commandName]='~/[scriptName]'
みたいな感じでコマンドを割り当ててあげれば良いのでは無いでしょうか。


とまあこんな感じです。
新年初プログラムでした。良いお年を。