RonPringadi
RonPringadi

Reputation: 1494

Bash script to delete keep last N files only

I have a bunch of log files and I would like to keep only the last 3 (N) files, the most recent ones. How do you do this in bash elegantly?

I have this script but it's kind of long.

The files could be something like:

my-file-pattern.log.2019-10-01
my-file-pattern.log.2019-10-02
my-file-pattern.log.2019-10-03
and so on

My script:

#!/bin/bash
function keepLastNOnly(){
    local WORKDIR="$1"
    local PATTERN="$2"
    local MAX=$3
    cd $WORKDIR 
    COUNT=$(ls -t $WORKDIR | grep $PATTERN|wc -l|grep -o -E '[0-9]+')
    while [ $COUNT -gt $MAX ]; do
        local TODEL=$(ls -t $WORKDIR | grep $PATTERN |tail -n 1)
        rm -rf "$TODEL"
        COUNT=$(ls -t $WORKDIR | grep $PATTERN|wc -l|grep -o -E '[0-9]+')
    done
}
keepLastNOnly "/MyDirectory/" "my-file-pattern.log" 3

Any shorter way?

Upvotes: 0

Views: 1594

Answers (4)

ufopilot
ufopilot

Reputation: 3975

#!/bin/bash

function keepLastNOnly(){
    local workdir="$1"
    local pattern="$2"
    local max="$3"
    awk -v max="$max" '
        NR<=max{ print "keeping " $0; next } 
        {   print "removing", $0 
            print |"rm -f " $0 
        }
    ' < <(find "${workdir}" -type f -name "${pattern}" | sort -r)
} 

keepLastNOnly . "my-file-pattern.log*" 3

$ ./test.sh 
keeping ./my-file-pattern.log.2019-10-08
keeping ./my-file-pattern.log.2019-10-07
keeping ./my-file-pattern.log.2019-10-06
removing ./my-file-pattern.log.2019-10-05
removing ./my-file-pattern.log.2019-10-04
removing ./my-file-pattern.log.2019-10-03
removing ./my-file-pattern.log.2019-10-02
removing ./my-file-pattern.log.2019-10-01

Upvotes: 0

Nik
Nik

Reputation: 1

Sort by time, new in a top. Skip 10 files in path, perform deletion of rest.

for rmfile in $(ls -lt /path/to/files/* | tail -n +11 | awk '{print $9}'); do
  echo "Deleting file ${rmfile}"
  rm -f ${rmfile}
done

Upvotes: 0

Eivind Tagseth
Eivind Tagseth

Reputation: 71

Keeping to the style of the question:

#!/bin/bash

function keepLastNOnly() {
    local WORKDIR="$1"
    local PATTERN="$2"
    local MAX=$3

    for file in `ls -t1 $WORKDIR | grep $PATTERN | head -n -3`; do
       rm $file
    done
}

The clue is the -n -3 flag to head.

Note that this version will keep the latest modified files, not the latest according to file name.

Upvotes: 3

Chris Maes
Chris Maes

Reputation: 37742

consider using logrotate which does all that for you, you just need to configure it:

https://linux.die.net/man/8/logrotate

Upvotes: 2

Related Questions