#!/usr/bin/perl
use
Term::ANSIColor
qw [
:constants color ] ;
$Term::ANSIColor::AUTORESET
= 1 ;
use
List::Util
qw [
max min sum sum0 reduce uniq ] ;
use
Cwd
qw [
getcwd abs_path ] ;
use
POSIX
qw[ strftime ]
;
sub
dtwhen ( $ ) ;
my
$time_start
= [ gettimeofday ] ;
my
$t0
=
$time_start
-> [0] ;
getopts
'0:2b:Df:nos'
, \
my
%o
;
my
@files
=
@ARGV
?
@ARGV
:
glob
'*'
;
$o
{2} = 1
if
$o
{D} ;
$o
{0} //= 1 ;
& main ;
exit
0 ;
END{
print
RESET
""
} ;
sub
main () {
my
%s2f
;
for
(
@files
) {
next
if
-d
$_
;
my
$size
= (
lstat
$_
) [7] ;
next
if
defined
$o
{b} &&
$size
<
$o
{b} ;
push
@{
$s2f
{
$size
}} ,
$_
;
my
@out
= (
$size
,
$_
) ;
}
my
$least
=
$o
{f} // 2 ;
my
@sizes
=
sort
{
$a
<=>
$b
}
grep
{ @{
$s2f
{
$_
} } >=
$least
}
keys
%s2f
;
my
$nfmt
=
do
{
my
$t
= max
@sizes
, 0 ;
my
$d
=
length
"$t"
;
"%${d}s"
} ;
for
my
$size
(
@sizes
) {
my
@files
=
sort
@{
$s2f
{
$size
} } ;
@files
=
sort
{(
stat
$a
)[9] <=> (
stat
$b
)[9] }
@files
if
$o
{n} //
$o
{o} ;
@files
=
reverse
@files
if
$o
{n} ;
my
%seenD
;
for
(
@files
) {
my
@t3
= (
stat
$_
)[8,9,10] ;
my
$ctx
= Digest::MD5->new;
unless
(
$o
{0}){
open
my
$FH
,
'<'
,
$_
or
die
"Can't open '$_': $!"
;
binmode
$FH
;
$ctx
->addfile(
$FH
);
close
$FH
;
}
utime
@t3
[0,1] ,
$_
unless
$o
{0} ;
my
$digest
=
$o
{0} ?
'---'
:
$ctx
->hexdigest ;
next
if
$o
{2} && !
$seenD
{
$digest
} ++ ;
if
(
$o
{D} && !
$o
{0} ) {
unlink
$_
;
next
} ;
my
@out
= (
sprintf
(
$nfmt
,
$size
) ,
$digest
,
map
( dtwhen
$_
,
@t3
) ,
$_
) ;
say
join
"\t"
,
@out
;
}
}
}
sub
dtwhen ( $ ) {
my
$fmt
=
abs
(
$_
[0] -
$t0
) >= 86400 * 180 ?
'%Y-%m-%d'
:
$o
{s} ?
'%m-%d %H:%M:%S'
:
'%m-%d %H:%M'
;
strftime
$fmt
,
localtime
$_
[0] ;
}
END{
exit
if
exists
$o
{v} &&
$o
{v} eq
"0"
;
say
STDERR
" -- "
, REVERSE ITALIC
" Process time: "
, CLEAR
" "
,
sprintf
(
"%.6f"
, tv_interval
$time_start
, [ gettimeofday ] ) ,
" second(s)."
;
}
sub
VERSION_MESSAGE {}
sub
HELP_MESSAGE {
$ARGV
[1] //=
''
;
open
my
$FH
,
'<'
, $0 ;
while
(<
$FH
>){
s/\$0/
$Script
/g ;
print
$_
if
s/^=head1// .. s/^=cut// and
$ARGV
[1] =~ /^o(p(t(i(o(ns?)?)?)?)?)?$/i ? m/^\s+\-/ : 1;
}
close
$FH
;
$o
{v} = 0 ;
exit
0 ;
}
=encoding utf8
=head1
このコマンドについては、ファイルの時刻情報を書き換えたり、消去する機能があるのに、デバグなどが不十分なので、
その危険性を理解して使うこと。
$0 files ..
オプション:
-0 0 : MD5ハッシュ値を算出する。ファイルのアクセス時刻やinode時刻を変える危険を確認する効果がある。
-b N : 処理対象とする最小のバイトサイズを指定。0バイトファイルを避けるなら1を指定。
-f N : 少なくとも何回出現したものだけを取り出すかの指定。初期値は2。
-n : 同じファイルサイズなら書換日時の新しい順 (newer)
-o : 同じファイルサイズなら書換日時の古い順 (older)
-s : 180日以内について、日時情報は秒単位で表示。
-2 : 同じファイルサイズで,同じハッシュ値のものについて、2番目以降を取り出す。
-D : 同じファイルサイズで,同じハッシュ値のものについて、2番目以降をファイル除去する。<-- 破壊的, 危険