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.
Asked
Active
Viewed 1.0k times
10
4 Answers
7
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=${f#ABC_}
date=${date%.log}
(( $date < $four_days )) && rm "$f"
done
jw013
- 50,274
- 9
- 137
- 141
glenn jackman
- 84,176
- 15
- 116
- 168
-
GNU date commands not working.. :( Any other way to get date which is 5 days before? – Nalu May 08 '12 at 06: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 08 '12 at 06:30
-
With help of uname -a got the following info: "SunOS badap01t 5.10 Generic_141444-09 sun4u sparc SUNW,SPARC-Enterprise" – Nalu May 08 '12 at 07:14
-
Question remains: what commands do you have available to get the current date? – Bram May 08 '12 at 08:47
-
If Tcl is installed: `four_days=$(echo "puts [clock format [clock scan {4 days ago}] -format %Y%m%d]" | tclsh)` – glenn jackman May 08 '12 at 13:05
-
Works like a charm for all files under a given directory. How about recursive? – praneel Apr 23 '15 at 13:48
-
@praneel, `shopt -s globstar nullglob; for f in **/ABC...` – glenn jackman Apr 23 '15 at 13:51
2
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
do
[[ $DATE -le $THRESHOLD ]] && rm -v $FILE
done
oHo
- 1,248
- 1
- 12
- 22
-
GNU date commands not working.. :( Any other way to get date which is 5 days before? – Nalu May 08 '12 at 06:04
1
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:
ABC_20120320.log
ABC_20120430.log
ABC_20120502.log
ABC_20120508.log
ABC_20120509.log
script.pl
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
Birei
- 7,924
- 2
- 22
- 14
-1
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
Thomas
- 926
- 1
- 7
- 13
-
3Don'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 07 '12 at 12:43