Shell script to delete all but the N newest files in a directory
(First, the cubby is finished, but it’s a more demanding writeup, so it’ll will come shortly.)
Couldn’t find something to do this via Google, so naturally I thought I’d share this once it was ready.
Do you ever want to keep just the N newest files in some directory. There’s no shortage of scripts out there to purge (or do something else to) all files over a certain age, and that’s great for log files and things which you know are always going to come in. But if I have a directory which is downloading files from an internet source of varying reliability, I don’t want to end up in a situation where I have no data in my work dir.
Enter keepnewest.sh, a little script I cooked up to do what I want: you specify a directory and a number and it keeps only the N newest files in your dir.
It makes judicious use of pipes and xargs and unix goodness to do the job reliably in a small amount of space. It will give you a usage statement if you run it with the wrong number of args, and returns a non-zero value if it fails (but it could fail even if it succeeded 99.9%. And it goes a little something like this:
#! /bin/sh# keepnewest
#
# Simple directory trimming tool to handle housekeeping
# Scans a directory and deletes all but the N newest files
#
# Usage: cleanup <dir> <number of files to keep>
#
# v 1.0 Piers Goodhew 1/mar/2007. No rights retained.
if [ $# -ne 2 ]; then
echo 1>&2 "Usage: $0 <dir> <number of files to keep>"
exit 1
fi
cd $1
files_in_dir=`ls | wc -l`
files_to_delete=`expr $files_in_dir - $2`
if [ $files_to_delete -gt 0 ]; then
ls -t | tail -n $files_to_delete | xargs rm
if [ $? -ne 0 ]; then
echo "An error ocurred deleting the files"
exit 1
else
echo "$files_to_delete file(s) deleted."
fi
else
echo "nothing to delete!"
fi
Enjoy!




Recommend protecting variables with braces just as a good habit:
$variable –> ${variable}
Means (in the future) you can do stuff like:
middle=uc
echo f${middle}k
- M0les.
… And you might also want to have an “exit 0″ at the end
This would do the same:
ls -1t “$1″ | tail -n +$2 | xargs -I{} -n1 rm “{}”
Nice use of the “-n +X” in tail, I’ll add that. But the one-liner is obviously without the feedback to the user should it fail.
(Also, anyone who wants to copy & paste the above, watch out: wordpress has done “smart” quotes which a shell won’t like.)
This script has a limitation when the directory contains subdirs. Since subdirs can’t be removed it throws the “error occured deleting files” message then.