General

Re: script to get the most recent updated file in a dir-tree

 
SOLVED
Go to solution
Hoefnix
Honored Contributor

script to get the most recent updated file in a dir-tree

Hi,

Does anyone know a solution to get the most recent updated file in a directory tree (including sub-dirs) and it's modification date/time?

I know you can use find (-mtime #day's) but this will not give the most recent updated file.
Also a ls -alt will not work for all possible sub-directies in the directory.
So I guess it will be a combination of find/ls/awk.

Ps. The next thread wil not work because it only search at 1 directory level.
http://forums1.itrc.hp.com/service/forums/bizsupport/questionanswer.do?threadId=85451

Regards,
Peter
13 REPLIES 13
Muthukumar_5
Honored Contributor

Re: script to get the most recent updated file in a dir-tree

Peter,

IT is really good question. I have tried level best to find with find | ls | sort ..etc..

It will breakup at some issues as,

1) file may be created today or long time back.. We can not use -mtime with find.

2) If we use ls -t then it will be useful for current directory

3) When using sort -Mb -k6, it sorts month but not data and timestamp.

I hope it is easy with perl. Wait for Procura or JRF.. to give that.. Mean time I will try with hard scripting.. :(

--
Muthu
Easy to suggest when don't know about the problem!
James R. Ferguson
Acclaimed Contributor

Re: script to get the most recent updated file in a dir-tree

Hi Peter:

Try this:

# find /pathname -xdev -type f|xargs ls -lt|head -1

Regards!

...JRF...
James R. Ferguson
Acclaimed Contributor
Solution

Re: script to get the most recent updated file in a dir-tree

Hi Peter:

Sorry, ENOCOFFEE!

# cat ./findfile
#!/usr/bin/perl
die unless @ARGV;
open( FH,"find $ARGV[0] -xdev -type f|" ) or die "Can't open $!\n";
while () {
chomp ($_);
$ts = (stat $_)[9];
if ($ts > $mtime) {
$mtime = $ts;
$file = $_;
}
}
print "$file\n";

Run as ./findfile dirname

Regards!

...JRF...
Hoefnix
Honored Contributor

Re: script to get the most recent updated file in a dir-tree

Guy's,

Thanks for your input.
I am rushing from one meeting to another so will test tomorrow and report back.

Cheers,
Peter
Victor Fridyev
Honored Contributor

Re: script to get the most recent updated file in a dir-tree

Hi,

Try also thjis:
#!/usr/bin/sh
rsub(){
OF=$1
NNF=$(find . -newer $OF -type f |head -1)
if [ -z "$NNF" ]; then
echo $OF
/bin/ls -ls $OF
exit
else
rsub $NNF
fi
}
cd $1
NF=$(/bin/ls -lat |grep -v ^d |grep -v ^l|awk 'NF>3 {print $NF;exit}')
rsub $NF


The script should be run as
script dirname


HTH
Entities are not to be multiplied beyond necessity - RTFM
Hoefnix
Honored Contributor

Re: script to get the most recent updated file in a dir-tree

Muthu,

Thanks for thinking with me, you where right about JRF.

Victor,

I like your solution because it uses only the default UNIX shell, but it is failing on files that have spaces in the filename.

JRF,

Your solution works very good. I am not experienced in Perl so many thanks for this lesson.

Cheers,
Peter
Arturo Galbiati
Esteemed Contributor

Re: script to get the most recent updated file in a dir-tree

Hi,
ll -Rt shows you for each directory the most recent updated file at the top
HTH,
Art
Ralph Grothe
Honored Contributor

Re: script to get the most recent updated file in a dir-tree

Hi Peter,

the task is fairly easy if we let the Perl standard module File::Find let do the main work.
(either type "perldoc File::Find" in a shell of your box, or see http://search.cpan.org/~nwclark/perl-5.8.7/lib/File/Find.pm for details)

In this sample code snippet I only look for ordinary files (viz. ignoring directories or Unix sockets etc.).
As you can see from the module's POD the File::Find::find function exspects a coderef as its 1st arg (or alternatively a hashref if you need to set certain switches that prescribe its descending behaviour etc.).
This coderef points to a so called callback function that is invoked on every item find() finds, and executes the code therein in situ (per default find() does a chdir() down the search tree, but you can prevent this if required).
All args that follow in the find() parameter list are starting directories that ought to be searched the whole tree down.
The stat() Perl built in of the namesake libc syscall delivers as its 10th item the mtime of the inode for the picked file
(see "perldoc -f stat").
The mtime is stored in so called epoche seconds (i.e. from 01.01.1970 00:00).
The time() syscall returns the epoche seconds that have passed up until now
("perldoc -f time").
Finally the Perl test operator -f (same as for shell scripts) tests whether the inode entry at hand refers to an ordinary file.
To avoid the extra expense for a second stat() syscall the usual Perl idiom is to use the underscore (viz. -f _) which says that you want to refer to the last stat-ed values.
This should suffice as explanation.
Of course, you could scramble this into a Perl oneliner in a "procura-like" manner, but sacrificing a bit readability.


use File::Find;

use strict;

our ($latest, $file);
find(sub { my $mtime = (stat)[9]; if (-f _ && $mtime > $latest) { $latest = $mtime; $file = $File::Find:
:name } }, '/var');
printf "%s\t%u\n", $file, time - $latest;

Madness, thy name is system administration
Hoefnix
Honored Contributor

Re: script to get the most recent updated file in a dir-tree

Ralph,

Thanks. Someone in my office pointed me already at this perl module and gave me a very heavy book that should explain it all.

But when I run your example script it did not work. First it complained about some undefined variables ($latest and $file) which I fixed, but now it complains about the sub routine "our" being undefined.

I think I should read some more websites(merijns website is pointing at some sites I should check) and books about perl before I feel comfortable using it.

Cheers,
Peter