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: