| 1 | #!/usr/bin/perl |
|---|
| 2 | |
|---|
| 3 | use strict; |
|---|
| 4 | use warnings; |
|---|
| 5 | use diagnostics; |
|---|
| 6 | |
|---|
| 7 | # -------------------------------------------------------------------------------- |
|---|
| 8 | |
|---|
| 9 | # skip files with the following extensions: |
|---|
| 10 | my @boring_extensions = ( |
|---|
| 11 | 'o', 'a', 'so', |
|---|
| 12 | 'gz', 'tgz', |
|---|
| 13 | 'class', 'jar', |
|---|
| 14 | 'elc', |
|---|
| 15 | 'lnk', |
|---|
| 16 | ); |
|---|
| 17 | |
|---|
| 18 | # skip files with the following names: |
|---|
| 19 | my @boring_files = ( |
|---|
| 20 | '.cvsignore', |
|---|
| 21 | 'TAGS', |
|---|
| 22 | ); |
|---|
| 23 | |
|---|
| 24 | # skip directories with the following full names: |
|---|
| 25 | my @boring_dirs = ( |
|---|
| 26 | 'bin', |
|---|
| 27 | ); |
|---|
| 28 | |
|---|
| 29 | # skip sub-directories with the following names: |
|---|
| 30 | my @boring_subdirs = ( |
|---|
| 31 | 'CVS', |
|---|
| 32 | '.svn', |
|---|
| 33 | '.git', |
|---|
| 34 | ); |
|---|
| 35 | |
|---|
| 36 | my @boring_namematches = ( |
|---|
| 37 | qr/^\#.*\#$/, # emacs autosaves |
|---|
| 38 | qr/^\.\#.*\.[0-9]+\.[0-9]+$/, # old cvs revisions |
|---|
| 39 | ); |
|---|
| 40 | my @boring_fullmatches = ( |
|---|
| 41 | ); |
|---|
| 42 | |
|---|
| 43 | my $max_print = 1000; # max lines to print |
|---|
| 44 | |
|---|
| 45 | # -------------------------------------------------------------------------------- |
|---|
| 46 | |
|---|
| 47 | my $ARBHOME = $ENV{'ARBHOME'}; |
|---|
| 48 | if (defined $ARBHOME) { |
|---|
| 49 | push @boring_extensions, 'genmenu'; |
|---|
| 50 | push @boring_extensions, 'stamp'; |
|---|
| 51 | push @boring_extensions, 'depends'; |
|---|
| 52 | push @boring_extensions, 'last_gcc'; |
|---|
| 53 | push @boring_extensions, 'last_compiler'; |
|---|
| 54 | |
|---|
| 55 | push @boring_fullmatches, qr/$ARBHOME\/lib\/ARB\.pm$/; |
|---|
| 56 | push @boring_fullmatches, qr/$ARBHOME\/PERL2ARB\/.*ARB\.(bs|xs|c|3pm)$/; |
|---|
| 57 | push @boring_fullmatches, qr/$ARBHOME\/PERL2ARB\/(debug|proto)\.h$/; |
|---|
| 58 | push @boring_fullmatches, qr/$ARBHOME\/PERL2ARB\/Makefile$/; |
|---|
| 59 | push @boring_fullmatches, qr/$ARBHOME\/TEMPLATES\/arb_build\.h$/; |
|---|
| 60 | push @boring_fullmatches, qr/$ARBHOME\/HELP_SOURCE\/(date\.xsl|html\.list|_index\.html)$/; |
|---|
| 61 | push @boring_fullmatches, qr/$ARBHOME\/AISC\/aisc$/; |
|---|
| 62 | push @boring_fullmatches, qr/$ARBHOME\/AISC_MKPTPS\/aisc_mkpt$/; |
|---|
| 63 | push @boring_fullmatches, qr/$ARBHOME\/.*\/GEN[CH]\//; |
|---|
| 64 | push @boring_fullmatches, qr/$ARBHOME\/GDEHELP\/helpfiles\.lst$/; |
|---|
| 65 | |
|---|
| 66 | push @boring_dirs, $ARBHOME.'/PROBE_SERVER/bin'; |
|---|
| 67 | push @boring_dirs, $ARBHOME.'/PROBE_SET/bin'; |
|---|
| 68 | push @boring_dirs, $ARBHOME.'/ARB_SOURCE_DOC'; |
|---|
| 69 | push @boring_dirs, $ARBHOME.'/HELP_SOURCE/Xml'; |
|---|
| 70 | push @boring_dirs, $ARBHOME.'/HELP_SOURCE/genhelp'; |
|---|
| 71 | push @boring_dirs, $ARBHOME.'/GDEHELP/HELP_GEN'; |
|---|
| 72 | push @boring_dirs, $ARBHOME.'/GDEHELP/HELP_DOC_GEN'; |
|---|
| 73 | push @boring_dirs, $ARBHOME.'/lib/help'; |
|---|
| 74 | push @boring_dirs, $ARBHOME.'/lib/help_html'; |
|---|
| 75 | push @boring_dirs, $ARBHOME.'/bin'; |
|---|
| 76 | } |
|---|
| 77 | |
|---|
| 78 | # -------------------------------------------------------------------------------- |
|---|
| 79 | |
|---|
| 80 | my @files = (); |
|---|
| 81 | |
|---|
| 82 | my %boring_extensions = map { $_ => 1; } @boring_extensions; |
|---|
| 83 | my %boring_files = map { $_ => 1; } @boring_files; |
|---|
| 84 | my %boring_subdirs = map { $_ => 1; } @boring_subdirs; |
|---|
| 85 | my %boring_dirs = map { $_ => 1; } @boring_dirs; |
|---|
| 86 | |
|---|
| 87 | sub scan_tree_recursive($); |
|---|
| 88 | sub scan_tree_recursive($) { |
|---|
| 89 | my ($dir) = @_; |
|---|
| 90 | # print "scan_tree_recursive '$dir'\n"; |
|---|
| 91 | opendir(DIR,$dir) || die "can't read directory '$dir'"; |
|---|
| 92 | my @subdirs = (); |
|---|
| 93 | foreach (readdir(DIR)) { |
|---|
| 94 | if (not /^[.]+$/o) { # ignore curr- and up-dir |
|---|
| 95 | my $fullname = $dir.'/'.$_; |
|---|
| 96 | if (not -l $fullname) { # ignore links |
|---|
| 97 | if (-d $fullname) { |
|---|
| 98 | if (not exists $boring_subdirs{$_} and |
|---|
| 99 | not exists $boring_dirs{$fullname}) |
|---|
| 100 | { |
|---|
| 101 | push @subdirs, $fullname; |
|---|
| 102 | } |
|---|
| 103 | } |
|---|
| 104 | else { |
|---|
| 105 | my $skip = 0; |
|---|
| 106 | if (exists $boring_files{$_}) { |
|---|
| 107 | $skip = 1; |
|---|
| 108 | } |
|---|
| 109 | elsif (/\.([^\.]+)$/ and exists $boring_extensions{$1}) { |
|---|
| 110 | $skip = 1; |
|---|
| 111 | } |
|---|
| 112 | else { |
|---|
| 113 | my $name = $_; |
|---|
| 114 | TEST1: foreach (@boring_namematches) { |
|---|
| 115 | if ($name =~ $_) { $skip = 1; last TEST1; } |
|---|
| 116 | } |
|---|
| 117 | if ($skip==0) { |
|---|
| 118 | TEST2: foreach (@boring_fullmatches) { |
|---|
| 119 | if ($fullname =~ $_) { $skip = 1; last TEST2; } |
|---|
| 120 | } |
|---|
| 121 | } |
|---|
| 122 | } |
|---|
| 123 | |
|---|
| 124 | if ($skip==0) { push @files, $fullname; } |
|---|
| 125 | } |
|---|
| 126 | } |
|---|
| 127 | } |
|---|
| 128 | } |
|---|
| 129 | closedir(DIR); |
|---|
| 130 | foreach (@subdirs) { |
|---|
| 131 | scan_tree_recursive($_); |
|---|
| 132 | } |
|---|
| 133 | } |
|---|
| 134 | |
|---|
| 135 | my $equality = '================'; |
|---|
| 136 | my $reg_parse_part = qr/^([ :]*)([^ :]+)/; |
|---|
| 137 | |
|---|
| 138 | sub diff2last_rec($$); |
|---|
| 139 | sub diff2last_rec($$) { |
|---|
| 140 | my ($this,$last) = @_; |
|---|
| 141 | |
|---|
| 142 | if (not $this =~ $reg_parse_part) { |
|---|
| 143 | if ($this =~ /^[ ]*$/) { return $this; } |
|---|
| 144 | die "can't parse '$this'"; |
|---|
| 145 | } |
|---|
| 146 | my ($this_space, $this_part, $this_rest) = ($1,$2,$'); |
|---|
| 147 | if (not $last =~ $reg_parse_part) { die "can't parse '$this'"; } |
|---|
| 148 | my ($last_space, $last_part, $last_rest) = ($1,$2,$'); |
|---|
| 149 | |
|---|
| 150 | my $part; |
|---|
| 151 | if ($this_part eq $last_part) { |
|---|
| 152 | $part = substr($equality, 1, length($this_part)); |
|---|
| 153 | } |
|---|
| 154 | else { |
|---|
| 155 | # print "'$this_part' ne '$last_part'\n"; |
|---|
| 156 | $part = $this_part; |
|---|
| 157 | } |
|---|
| 158 | |
|---|
| 159 | return $this_space.$part.diff2last_rec($this_rest, $last_rest); |
|---|
| 160 | } |
|---|
| 161 | |
|---|
| 162 | my $lastMod = undef; |
|---|
| 163 | sub diff2last($) { |
|---|
| 164 | my ($mod) = @_; |
|---|
| 165 | if (defined $lastMod) { |
|---|
| 166 | my $newmod = diff2last_rec($mod, $lastMod); |
|---|
| 167 | $lastMod = $mod; |
|---|
| 168 | $mod = $newmod; |
|---|
| 169 | } |
|---|
| 170 | else { |
|---|
| 171 | $lastMod = $mod; |
|---|
| 172 | } |
|---|
| 173 | return $mod; |
|---|
| 174 | } |
|---|
| 175 | |
|---|
| 176 | sub max($$) { |
|---|
| 177 | my ($a,$b) = @_; |
|---|
| 178 | return $a if $a>$b; |
|---|
| 179 | return $b; |
|---|
| 180 | } |
|---|
| 181 | |
|---|
| 182 | sub readable_age($) { |
|---|
| 183 | my ($modtime) = @_; |
|---|
| 184 | my $age = time - $modtime; |
|---|
| 185 | if ($age<60) { return $age.'s'; } |
|---|
| 186 | $age = int($age/60); if ($age<60) { return $age.'m'; } |
|---|
| 187 | $age = int($age/60); if ($age<24) { return $age.'h'; } |
|---|
| 188 | $age = int($age/24); if ($age<14) { return $age.'d'; } |
|---|
| 189 | my $weeks = int($age/7); if ($weeks<9) { return $weeks.'w'; } |
|---|
| 190 | my $months = int($age/30); if ($months<12) { return $months.'M'; } |
|---|
| 191 | my $years = int($age/365); |
|---|
| 192 | return $years.'Y'; |
|---|
| 193 | } |
|---|
| 194 | |
|---|
| 195 | sub perform_search() { |
|---|
| 196 | my $root = `pwd`; |
|---|
| 197 | chomp($root); |
|---|
| 198 | $root =~ s/[\/\\]+$//g; |
|---|
| 199 | |
|---|
| 200 | scan_tree_recursive($root); |
|---|
| 201 | my %filedate = (); |
|---|
| 202 | |
|---|
| 203 | my $del = length($root)+1; |
|---|
| 204 | @files = map { substr($_,$del); } @files; |
|---|
| 205 | |
|---|
| 206 | foreach (@files) { |
|---|
| 207 | my $modtime = (stat($_))[9]; |
|---|
| 208 | if (not defined $modtime) { die "Can't stat file '$_'"; } |
|---|
| 209 | $filedate{$_} = $modtime; |
|---|
| 210 | # print scalar(localtime($modtime))." $_\n"; |
|---|
| 211 | } |
|---|
| 212 | |
|---|
| 213 | my @sorted = sort { |
|---|
| 214 | $filedate{$b} <=> $filedate{$a}; |
|---|
| 215 | } @files; |
|---|
| 216 | |
|---|
| 217 | if (scalar(@sorted)<$max_print) { $max_print=scalar(@sorted); } |
|---|
| 218 | |
|---|
| 219 | my $maxlen = 0; |
|---|
| 220 | foreach (my $i=0; $i<$max_print; ++$i) { |
|---|
| 221 | my $len = length($sorted[$i]); |
|---|
| 222 | if ($len > $maxlen) { $maxlen = $len; } |
|---|
| 223 | } |
|---|
| 224 | |
|---|
| 225 | my $spacer = " "; |
|---|
| 226 | while (length($spacer) < $maxlen) { $spacer .= $spacer; } |
|---|
| 227 | |
|---|
| 228 | print "find_newest_source: Entering directory `$root'\n"; |
|---|
| 229 | foreach (my $i=0; $i<$max_print; ++$i) { |
|---|
| 230 | $_ = $sorted[$i]; |
|---|
| 231 | my $len = length($_); |
|---|
| 232 | print "$_:1: ".substr($spacer,0,max($maxlen-$len,0)). |
|---|
| 233 | "mod: ".diff2last(scalar(localtime($filedate{$_}))). |
|---|
| 234 | " [ ".sprintf("%3s",readable_age($filedate{$_}))." ]\n"; |
|---|
| 235 | } |
|---|
| 236 | print "find_newest_source: Leaving directory `$root'\n"; |
|---|
| 237 | } |
|---|
| 238 | |
|---|
| 239 | perform_search(); |
|---|