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

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

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

(更に改訂しました)undoコマンドの不具合が表出しました

Perl

お疲れ様です。


rmコマンドでゴミ箱送り、そこからのUndo、そしてゴミ箱を空にするcleanTrashと、
自分で書いたスクリプト群を実際に使っております。
それがこちら

悲劇勃発

さて先日、誤って.gitignoreファイルをrmしてしまいまして。
「おっとっと、やっちまったぜ。でも大丈夫。ゴミ箱に入っているだけさ……」
と思い、軽い気持ちでundoしてみましたら、おやおや、ファイルが復活しないではありませんか。
「不具合かな? 復活してないってことは、ゴミ箱ファイルにまだ残ってるのかな?」
と、ゴミ箱ファイルを覗いてみましても、.gitignoreファイルはどこにも無く……
「!!!」
仕方がないので、"git reset --soft HEAD^"と打ち込んで事なきを得ましたとさ。
あって良かったgit

過ちを潰す

ただ、「いつまでもあると思うな親とgit」と申しますように、
そのスクリプトの不具合を看過する訳には参りません。
どうしたものか、とソースコードを観てみましたら一発で誤りを発見してしまいました。
"glob"の使い方がマズかったんですね。


globはドット(.)から始まるファイル・ディレクトリを自動的に除外してしまうので、
取得するには明示的に「ドットから始まるファイルも持ってきて」と指示する必要があります。
それをすっかり失念しておりました。
"はじめてのPerl"にも親切に書いてたじゃないか! 俺の馬鹿!!

・ドットから始まるファイル・ディレクトリを除外

glob "$targetDirectory/*";

・ドットから始まるファイル・ディレクトリも持ってきて

glob "$targetDirectory/* $targetDirectory/.*";


という訳なので、そこの部分を直しました。そこの部分意外もちょろっと直しました。
今回直したのはUndoだけです。
以下ソースコード

Undo

#! /usr/bin/perl

use 5.010;
use File::Path;

#以下に記述されている「ゴミ箱のディレクトリ」には、
#任意の場所に自分で作った「ゴミ箱ディレクトリ」のパスを
#記述してください。
#e.g. : "/home/owner/.Trash/"
my $trashDirectory = "ゴミ箱のディレクトリ";
unless( $trashDirectory =~ m#/$# ){
    $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/* $targetDirectory/.*";
my $targetUndoFile;
foreach( @targetUndoFileList ){
    $targetUndoFile = $_;
    s#^$targetDirectory/##;
    unless( $targetUndoFile =~ /\.$/ ){
        rename $targetUndoFile, $targetUndoLocation."/".$_;
        say "Undo : $targetUndoFile -> $targetUndoLocation/";
    }
}

rmtree $targetDirectory;


こんな感じでした。この調子じゃまだまだ不具合が出てくるんじゃ……簡単なスクリプトなのに……