[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: OT: Alternatives to ls for sorting files by modification time



Adrian von Bidder wrote:
find "$BACKUP_DIR/arc" -name '*.arc' -printf '%A@:%p\n' \
	| sort -g  -t : \
	| cut -d : -f 2- \
	| head -n "$NUM_OF_FILES" \
	| xargs -r rm -f


Another option might be to re-cast the problem a bit. If you're just trying to keep the number of files in the directory under control, and don't specifically need to keep the NUM_OF_FILES most recent files, the idea of keeping files that are newer than a certain age fits "find" a bit more cleanly. For instance

    find . -type f -name '*.arc' -not -amin 86400 -print \
        | xargs -r rm -f

would be "delete any arc files that haven't been accessed in the last 24 hours".

If somebody wants to do some clever scripting: I have a similar need,
but not yet found a simple solution: I want to purge some cache
directory and just leave the most recently accessed k megabytes. File
sizes vary greatly, so file count won't help much.

There's probably a nice, elegant way to do this one in shell script, but I'd be tempted to just throw it over to Perl. Warning: this script will break if the list of file names gets too big to hold in memory:

#!/usr/bin/perl -w

use strict;

# print usage
if ($#ARGV != 1) {
    print "usage: $0 <directory> <megabytes>\n";
    exit 1;
}

# get files from directory
if (! opendir DIR, "$ARGV[0]") {
    die "couldn't open directory $ARGV[0]";
}
my @fileNames = readdir DIR;
closedir DIR;

# get file sizes and access times
my @fileInfo;
my $BYTES_PER_MB = 1024 * 1024;
my $ACCESS_IDX = 8; # see "stat" in man perlfunc
foreach my $file (@fileNames) {
    my $fullName = "$ARGV[0]/$file";
    if (-f "$fullName") {
        my @stat = stat "$fullName";
        push @fileInfo, [$fullName, $stat[$ACCESS_IDX],
                         $stat[7] / $BYTES_PER_MB];
    }
}
@fileNames = ();

# sort by access time, most recent first
@fileInfo = sort {$b->[1] <=> $a->[1]} @fileInfo;

# Once the number of megabytes of accessed files exceeds
# the command line parameter, print the file names.
my $totMB = 0;
foreach my $info (@fileInfo) {
    $totMB += $info->[2];
    if ($totMB > $ARGV[1]) {
        print "$info->[0]\n";
    }
}

Hope this helps!

- Jeff



Reply to: