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!

Advertisements
  1. 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.

  2. … And you might also want to have an “exit 0” at the end

  3. 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.)

    • indijan
    • December 5th, 2010

    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.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: