[KLUG Members] find a file by date

Jamie McCarthy jamie at mccarthy.vg
Fri Dec 10 11:44:48 EST 2004


pescej at sprl.db.erau.edu (John Pesce) writes:

> how can I print a list of files, under a tree, with full path that have
> the same date as a particular file, when I do ls -l ?

OK, to clarify, "ls -l" emits modification dates in the timezone that
the machine is set to.

If you really mean precisely the same day, then for a file modified at
2001-11-19 00:00:01 EST, you would want to print a list of files last
changed between 2001-11-19 00:00:00 EST and 2001-11-19 23:59:59 EST.

My guess, though, is that you mean something a little looser, that you
just want "files changed around the same time as," maybe with a
plus-or-minus of 12 hours?

I'm going out on a limb here just for fun.  But if that is what you
meant, here's how I'd do that in perl:

perl -MFile::Find -le '$m = -M shift @ARGV; die "cannot stat" unless $m; finddepth(sub { print $File::Find::name if abs($m - -M $_) < 0.5 }, @ARGV)'

The first statement shifts the first file off the command line,
stats it to get its modification time (in days since this perl
command was invoked), and stores it in $m.  If this can't be done,
that first file was unreadable so it emits an error and exits.

The "within 12 hours" code is the

    abs($m - -M $_)

which evaluates to the absolute value of the difference between the
modification of the first file specified ($m) and the modification
time (-M) of the current file being looked at ($_), in days.

For example, to ls files in the source tree I'm currently looking at
which were modified within a 12 hour radius of the file
Slash/Slash.pm, I can do this:

jamie at daisy:~/slash.cvs$ perl -MFile::Find -le '$m = -M shift @ARGV; die "cannot stat" unless $m; finddepth(sub { print $File::Find::name if abs($m - -M $_) < 0.5 }, @ARGV)' Slash/Slash.pm . | xargs ls -ld
drwxr-sr-x  13 jamie jamie  4096 Nov 27 13:50 ./Slash
drwxr-sr-x   2 jamie jamie  4096 Nov 27 13:50 ./Slash/CVS
-rw-r--r--   1 jamie jamie   293 Nov 27 13:50 ./Slash/CVS/Entries
-rw-r--r--   1 jamie jamie 56046 Nov 27 13:50 ./Slash/Slash.pm
-rw-r--r--   1 jamie jamie  8875 Nov 27 13:54 ./themes/itmanagersjournal.com/templates/editComm;users;default
-rw-r--r--   1 jamie jamie  8753 Nov 27 13:54 ./themes/linux.com/templates/editComm;users;default
-rw-r--r--   1 jamie jamie  8875 Nov 27 13:54 ./themes/newsforge.com/templates/editComm;users;default
-rwxr-xr-x   1 jamie jamie 46820 Nov 27 13:50 ./themes/slashcode/htdocs/comments.pl
-rw-r--r--   1 jamie jamie  2427 Nov 27 13:50 ./themes/slashcode/templates/data;comments;default
-rw-r--r--   1 jamie jamie 11247 Nov 27 13:50 ./themes/slashcode/templates/editComm;users;default

The disadvantage of this, obviously, is that it's more complicated
than the other solutions already put forth.  The advantage is that
it's more flexible.  If you want to expand your search to find files
within 2 or 3 days, for example, there simply is no good way to do
that using ls (just thinking about handling month boundaries gives
me a headache).

The perl code can easily handle any time period, just change the
"0.5" value -- or it can change to a "newer than" or "older than"
algorithm if you want that, for example.

And the ls solution won't work for files younger than about six
months on my system, and varying durations on other systems, since
newer files are listed with their mod times instead of the mod year.

Perl is installed on every un*x system... do "perldoc File::Find"
for the documentation of that module.

You could also of course create a file with this perl script:

    #!/usr/bin/perl -l
    use File::Find;
    $m = -M shift @ARGV;
    die "cannot stat" unless $m;
    finddepth(sub {
        print $File::Find::name if abs($m - -M $_) < 0.5
    }, @ARGV)

If you named that "timefind" and chmod it executable, then you'd
invoke it like:

    timefind filename directory1 [directory2, directory3...]
-- 
  Jamie McCarthy
 http://mccarthy.vg/
  jamie at mccarthy.vg



More information about the Members mailing list