Find Oldest file in a directory tree

This might just be one command.

Any1 having the solution?

Thanks,
Rahul.

I think

ls -gt

would be one way of doing it. This will give a shortened version of the long list with the oldest files being listed in the end of the list. This should list them by the timestamp in descending order.

i guess g is ignored by ls, the below one will work anyway

ls -1t|tail -1

1 lists the output of ls as a column
t sorts it by time
tail -1 lists the last item in the list

1 Like

This will only give me the oldest file in the current directory.

What about searching the oldest file in the subdirectories?

Can we do it with find??

Try and adapt this ksh script :

#!/usr/bin/ksh
#
# Usage: $0 [directory]
#
oldest_file=

ls -1R ${1-} | \
awk -v dir="${1-}" '
        BEGIN {
           if (dir !~ /\/$/) 
              dir = dir "/"
           oldest_file_in_dir = 1;
        }
        /:$/ {
           dir = substr($0,1,length-1) "/";
           oldest_file_in_dir = 1;
           next;
        }
        oldest_file_in_dir {
           print dir  $0;
           oldest_file_in_dir = 0;
           next;
        }
    ' | \
while read file
do
   if [ -z "$oldest_file" ]
   then
      oldest_file="$file"
   else
      [[ "$file" -nt "$oldest_file" ]] && continue
      oldest_file="$file"
   fi
done

echo "Oldest File: $oldest_file"

Jean-Pierre.

I am trying to do something simpler as follows:

$find . -name "*" -exec ls -lrt {} \; |sort -k8 | more

But this gives me files in the ascending order of years

2003
2003
..
..
2004
..
..
2005

Now , I want to sort these further by month, day and time.

Any inputs??

deleted... sorry

I think, I have found it. Not really confident though

$find . -name "*" -exec ls -lrt {} \; |sort -k8,8 -k6M,6M -k7,7n | grep '^-' | head -1

This gave me the oldest file in a particualr directory. Not sure, if this would work always.

Thanks All.

I feel we should not sort based on the ls -lrt output because it contains the month in MMM format and not in number format, hence we can't sort...

here is small perl script... filedate.pl

#!/usr/bin/perl
#Argument of directory name is required

open(PTR,"find $ARGV[0] |");

my $str;

while($str=<PTR>)
{
chomp $str;

my ($hr,$mn,$day,$mnth,$year)=(localtime((stat($str))[9]))[1,2,3,4,5];

$mnth+=1;
$year+=1900;

printf("$year%02d%02d%02d%02d $str\n",$mnth,$day,$hr,$mn);
}

close PTR;

save the above file and give executable permission...
after that

$filedate.pl <DIR NAME> | sort

you can sort according to ur requirement... filedate.pl will give you the date of file in yyyymmddhhmm format....

I think the parameter
sort -k6M,6M

will sort the date month format as Jan, Feb, Mar,... in the ascending order. This what the man page says for the -M option. If that's not the case, please let me know.

I am using Sun Solaris 5.8

Thanks.
Rahul.

The -M option is not not available for the find command on my AIX box

Jean-Pierre.

Try this:

find <directory> -type f | xargs ls -ltr

Should sort all the files in the directory in order of oldest to newest.

Remember what xargs does for a living. If there are too many filenames to fit on one command line, xargs will construct as many command lines as needed to process them all. The set of filenames output by each commandline will be sorted by date. But the overall list of filenames will not be sorted. But in the special case where there are so few filenames that one command line is enough, this will work.

Id idn't get that. YOu mean to say if the search list is too long, the above won't work? I have a huge list of files to be searched in a specific partition which takes upto 47GB space. All this effort just to find the oldest file in this partition.

Please let me know if i interpreted it incorrectly.

Thanks.
Rahul.

Well, yes. As Perderabo said, for a large number of files, the 'find | xargs' won't work - definitely not for your 47GB of files. Use mahendramahendr's perl script to do the job for you.

#! /usr/bin/ksh

touch -t $(($(date "+%Y") + 1))$(date "+%m%d%H%M") notfound
OLDEST=notfound
find . -type f | while read f ; do
        [[ $f -ot $OLDEST ]] && OLDEST=$f
done
echo oldest file is $OLDEST
rm notfound
exit 0

Hi,

I found the perl script helpful, thanks for posting it. However, I think there is one small bug in it.

I think it should be
($mn,$hr,$day,$mnth,$year)=...

$ perldoc -f localtime
localtime EXPR
localtime
Converts a time as returned by the time function to a 9-element
list with the time analyzed for the local time zone. Typically
used as follows:

               \#  0    1    2     3     4    5     6     7     8
               \($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst\) =
                                                           localtime\(time\);

[...]

in all the subdirectories...

find . -type f -printf "%T@ %p \n" | sort -n -k 1,1 | awk '{print $2}'

Tim

Here is a perl script that I wrote for some commercial radio stations that want to delete the oldest archive file out of subdirectories from a root directory...

#!/usr/bin/perl

# This will sort all the files in various subdirectories by creation date.
# find . -type f -printf "%T@ %p \n" | sort -n -k 1,1 | awk '{print $2}'

$ls = "/usr/bin/find";
$df = "/bin/df -k";
$grep = "/bin/grep";
$lookfor = "*.mp3";
$dir = "/usr/local/public/archive/";
$percent = 95;

$fullfile = $dir . $lookfor;

open(LS_T, "$ls $dir -type f -printf '%T@ %p \n' | /usr/bin/sort -n -k 1,1 | /usr/bin/awk '{print \$2}'|") or die "Can't do $ls";
$i=0;
while(<LS_T>){
        chop;
        $filename = $_;
        $result=`$df $dir | $grep -v Filesystem`;
        chop $result;
        $_ = $result;
        tr/ / /s;
        ($fs,$kbytes,$used,$avail,$percentused,$mountedon) = split / /;
        chop $percentused;
        if ($percentused >= $percent){
                print "deleting \'$filename\'\n";
                `rm "$filename"`;
                $i++;
        } else {
                exit;
        }
}

Ok... Found a bug soon as I posted this. In the previous example the "awk" will only print out the string after the number up to the end of the line or another space. Not good if you have files or directories with spaces. This would work better. :slight_smile:

find . -type f -printf "%T@ %p \n" | sort -n -k 1,1 | sed 's/^[0-9]* //'