#!/usr/bin/perl -w # (C) 2003-2007 Willem Jan Hengeveld # Web: http://www.xs4all.nl/~itsme/ # http://wiki.xda-developers.com/ # # $Id$ # use strict; use Getopt::Long; use Cwd; my %monthnames=(Jan=>1, Feb=>2, Mar=>3, Apr=>4, May=>5, Jun=>6, Jul=>7, Aug=>8, Sep=>9, Oct=>10, Nov=>11, Dec=>12); # processes output of 'dir /s' and converts it to easily greppable # lines with data, size, fullpath # and of ls --full-time -lR ( gnu ls ) # and of ls -lTaR ( osx ls ) my $relative_to_cwd; my $dotdrive='z'; sub usage { return <<__EOF__ Usage: dir ... | updatedb [-c] -c : relative to current dir -s DRV : substitute driveletter for './' __EOF__ } GetOptions( "c"=>\$relative_to_cwd, "s=s" => \$dotdrive, ) or die usage(); my $basedir=""; my @base; if ($relative_to_cwd) { $basedir= getcwd; @base= split /\\/, $basedir; } if (!@ARGV) { processfile("-") } else { for my $filename (@ARGV) { processfile($filename) } } sub getrelative { my ($curdir, $basedir)= @_; if (lc($curdir) eq lc($basedir)) { return ""; } elsif (lc(substr($curdir, 0, length($basedir)+1)) eq lc($basedir."\\")) { return substr($curdir, length($basedir)+1); } else { my @cur= split /\\/, $curdir; my $i=0; while ($i<@base && $i<@cur && lc($base[$i]) eq lc($cur[$i])) { $i++; } return "..\\" x ( @base-$i ) . join("\\", @cur[$i..$#cur]); } } sub processfile { my $filename= shift; my $pathsep= "/"; $basedir =~ s{[\\/]}{$pathsep}g; if ($filename eq "-") { *FH=*STDIN; } else { open FH, "<", $filename or die "$filename: $!\n"; } # initialize to '.' for ls -lR output my $curdir= "$dotdrive:"; while () { s/\s+$//; if (/^ Directory of (.*)$/) { # dir header of windows dir listing (my $dirname=$1) =~ s{[\\/]$}{}; $dirname =~ s{[\\/]}{$pathsep}g; $curdir= $relative_to_cwd ? getrelative($dirname, $basedir) : $dirname; } elsif (/^(.*):$/) { # dir header in ls-lr listing (my $dirname=$1) =~ s{[\\/]$}{}; $dirname =~ s{[\\/]}{$pathsep}g; $curdir= $relative_to_cwd ? getrelative($dirname, $basedir) : $dirname; $curdir =~ s/^\.\//$dotdrive:\//; } elsif (/^([-dl])(?:[rsS-][w-][x-]){3}\s\d+\s+(\d+)\s+(\S+\s+\S+):\d\d\.\d+\s\S+\s(\S.*?)\/?$/) { # -rw-r--r-- 0 21401 2007-11-07 09:02:58.000000000 +0100 .bash_history my ($type, $size, $datetime, $filename)= ($1, $2, $3, $4); next if ($filename eq "." || $filename eq ".."); if ($type eq "d") { printf("%-16s %s%s%s%s\n", $datetime, $curdir, $pathsep, $filename, $pathsep); } elsif ($type eq "-") { printf("%-16s %11d %s%s%s\n", $datetime, $size, $curdir, $pathsep, $filename); } } elsif (/^([d-])(?:[rsS-][w-][x-]){3}\s+\d+\s\w+\s+\w+\s+(\d+)\s([A-Z][a-z][a-z])\s+(\d+)\s+(\S+)\s+(\d+)\s(\S.*)\/?$/) { # -rw-r--r-- 1 itsme itsme 9336 Feb 28 12:00:53 2008 x.old my ($type, $size, $mon, $day, $time, $year, $filename)= ($1, $2, $3, $4, $5, $6, $7); next if ($filename eq "." || $filename eq ".."); my $datetime= sprintf("%04d-%02d-%02d %s", $year, $monthnames{$mon}, $day, $time); if ($type eq "d") { printf("%-16s %s%s%s%s\n", $datetime, $curdir, $pathsep, $filename, $pathsep); } elsif ($type eq "-") { printf("%-16s %11d %s%s%s\n", $datetime, $size, $curdir, $pathsep, $filename); } } elsif (/^([d-])(?:[rsS-][w-][x-]){3}\s+\d+\s+\w+\s+\w+\s+(\d+)\s(\w\w\w\s.\d\s.\d.\d\d)\s(.*)/) { # drwxrwxr-x 2 0 3 96 Sep 14 2007 dist my ($type, $size, $datestr, $filename)= ($1, $2, $3, $4); next if ($filename eq "." || $filename eq ".."); my $datetime; if ($datestr =~ /^(\w\w\w)\s+(\d+)\s+(\d+)$/) { my ($mon, $day, $year)= ($1,$2,$3); $datetime= sprintf("%04d-%02d-%02d ??:??", $year, $monthnames{$mon}, $day); } elsif ($datestr =~ /^(\w\w\w)\s+(\d+)\s+(\d+:\d+)$/) { my ($mon, $day, $hhmm)= ($1,$2,$3); my @t=localtime time(); my $year= $t[5]+1900; $datetime= sprintf("%04d-%02d-%02d %s", $year, $monthnames{$mon}, $day, $hhmm); } if ($type eq "d") { printf("%-16s %s%s%s%s\n", $datetime, $curdir, $pathsep, $filename, $pathsep); } elsif ($type eq "-") { printf("%-16s %11d %s%s%s\n", $datetime, $size, $curdir, $pathsep, $filename); } } elsif (/^(\S+\s+\S+(?:\s\w\w)?)\s+\s+(\S.*)$/) { # dir entry my ($thisdatetime, $thisdirname)= ($1, $2); next if ($thisdirname eq "." || $thisdirname eq ".."); $thisdatetime= convertToYmd($thisdatetime); printf("%-16s %s%s%s\\\n", $thisdatetime, $curdir, $pathsep, $thisdirname); } elsif (/^(\S+\s+\S+(?:\s\w\w)?)\s+([0-9,]+)\s(\S.*)$/) { # file entry my ($datetime, $size, $filename)= ($1, $2, $3); $size =~ s/[ ,]//g; $datetime= convertToYmd($datetime); printf("%-16s %11d %s%s%s\n", $datetime, $size, $curdir, $pathsep, $filename); } elsif (/^$/ || /^\s+[0-9,]+\s+File\(s\)\s+[0-9,]+\s+bytes$/ || /^ Volume in drive \w / || /^ Volume Serial Number is / || /^\s+Total Files Listed:/ || /^total\s\d+/ || /^\s+[0-9,]+\s+Dir\(s\)\s+[0-9,]+\s+bytes free/) { # ignore } else { #print "unknown line $_\n"; } } close FH; } sub convertToYmd { my $mdyhm= shift; if ($mdyhm =~ m{(\d+)/(\d+)/(\d{4})\s+(\d+):(\d+)([ap])}) { my ($m, $d, $y, $hh, $mm, $ampm)= ($1,$2,$3,$4,$5,$6); if ($ampm eq "p" && $hh!=12 ) { $hh += 12; } elsif ($ampm eq "a" && $hh eq "12") { $hh= 0; } return sprintf("%04d-%02d-%02d %02d:%02d", $y, $m, $d, $hh, $mm); } else { # probably yyyy-mm-dd hh:mm $mdyhm =~ s/\s+/ /g; return $mdyhm; } }