I want to delete log files which are older than 5 days from a directory. But deletion should not be based on the timestamp of file. It should be based on the name of file. For Example todays date is 07/05/2012 and the directory contains 10 files of names like ABC_20120430.log, ABC_20120429.log, ABC_20120502.log, ABC_20120320.log etc. I want to be able to remove the files by extracting the date from the name of the file.


Based on date from filename:

THRESHOLD=$(date -d "5 days ago" +%Y%m%d)
ls -1 ABC_????????.log | 
  sed 'h;s/[_.]/ /g;G;s/\n/ /' | 
  while read A DATE B FILE
     [[ $DATE -le $THRESHOLD ]] && rm -v $FILE
  • GNU date commands not working.. :( Any other way to get date which is 5 days before? – Nalu May 8 '12 at 6:04

I think @oHessling almost has it: Don't parse ls, and you can do more in bash:

four_days=$(date -d "4 days ago" +%Y%m%d)
for f in ABC_[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].log; do
  (( $date < $four_days )) && rm "$f"
  • GNU date commands not working.. :( Any other way to get date which is 5 days before? – Nalu May 8 '12 at 6:04
  • 1
    @Naren: what OS are you on? If you don't have GNU date, we need to know what you do have. – Mat May 8 '12 at 6:30
  • With help of uname -a got the following info: "SunOS badap01t 5.10 Generic_141444-09 sun4u sparc SUNW,SPARC-Enterprise" – Nalu May 8 '12 at 7:14
  • Question remains: what commands do you have available to get the current date? – Bram May 8 '12 at 8:47
  • If Tcl is installed: four_days=$(echo "puts [clock format [clock scan {4 days ago}] -format %Y%m%d]" | tclsh) – glenn jackman May 8 '12 at 13:05

One way using perl:

Content of script.pl:

use warnings;
use strict;
use Time::Local qw/timelocal/;
use File::Spec;

## Process all input files.
while ( my $file = shift @ARGV ) { 

    ## Remove last '\n'.
    chomp $file;

    ## Extract date from file name.
    my ($date) = $file =~ m/.*_([^.]+)/ or next;

    ## Extract year, month and day from date.
    my ($y,$m,$d) = $date =~ m/(\d{4})(\d{2})(\d{2})/ or next;

    ## Get date in seconds.
    my $time = timelocal 0, 0, 0, $d, $m - 1, $y - 1900 or next;

    ## Get date in seconds five days ago.
    my $time_5_days_ago = time - 5 * 24 * 3600;

    ## Substract them, and if it is older delete it and print the
    ## event.
    if ( $time - $time_5_days_ago < 0 ) { 
        unlink File::Spec->rel2abs( $file ) and printf qq[%s\n], qq[File $file deleted];

To test it I create some files:

touch ABC_20120430.log ABC_20120502.log ABC_20120320.log ABC_20120508.log ABC_20120509.log

Check them with ls -1:


Run the script like:

perl script.pl *.log

With following output:

File ABC_20120320.log deleted
File ABC_20120430.log deleted
File ABC_20120502.log deleted

What you could do instead is use the fact that your filenames will sort in chronological order. For instance, to keep the last 5 files:

ls ABC_????????.log | head -n-5 | xargs rm
  • 3
    Don't use xargs with rm unless you know you are killing kittens every time you do. It's just a bad idea, if you don't know why do some research and learn that there are always better ways to approach any problem that this could be a solution for. – Caleb May 7 '12 at 12:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.