Operating System - HP-UX
1826498 Members
1842 Online
109692 Solutions
New Discussion

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
James R. Ferguson
Acclaimed Contributor

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

Hi Peter:

While I didn't use perl's Find module, but rather called the system's 'find' to begin the work, the approach we both took is similar.

I've attached a better version of what I first wrote. It's not biased -- it reports all files with the same, most recent timestamp.

See the attached!

Run as:

# ./mfile dirname

You can specify multiple directories as arguments, too.

Regards!

...JRF...
Hoefnix
Honored Contributor

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

JRF,

This looks great. I am already using your first script because that fits already my requirements. I am extending it with other checks using the output of the stat function in an array. This saves me running trough the tree structure multiple times, which I should have done without a perl solution.
(I needed to check also the data on permissions/group ownerships etc.., that is now easy with this perl script.)

Many thanks for your help in putting me in the right direction.

I leave this thread open til Monday to see if anyone can think of some other solution. It's always nice to see how many people can come up with different solutions with the same result.

Peter
Ralph Grothe
Honored Contributor

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

Peter,

that your Perl compiler complained about undeclared variables $latest and $file,
and moaned about an undefined sub "our"
indicates to me that you run it with a very dated Perl installation.
Actually, the our type was introduced with Perl 5.6 to replace the somewhat awkward "use vars" pragma.
I suggest you update your Perl
(if that is possible for you).
What is your Perl version?
(run "perl -v", or "perl -V")
Had I included the line

require '5.006';

then your Perl compiler should have exitetd with a meaningful message.

Besides, it was silly of me to declare the variables as our.
Just substitue the "our" with "my",
and it should execute with your Perl.

Or in fact you could get rid of any variable declaration at all, and remove the line with the "use strict" pragma.
For such a tiny bit of code its perfectly in order to have all variables implicitly declared as package globals (same as prepending an "our" at declaration with a Perl >= 5.6)
This is what the compiler silently assumes.
But for any Perl code extending a hundred lines or using different namespaces (viz. packages/modules) it should be mandatory to "use strict".

Apropos, if you strip off the -f test
then every kind of file (in the Unix sense) will be taken into account.
Madness, thy name is system administration
Hoefnix
Honored Contributor

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

All,

Thanks for the instructive input you all gave me.

Cheers,
Peter