How can I count the number of files in a directory and delete the oldest if the number exceeds 5

In pure Bash without loops:

ls -t | tail -n +6 | xargs -d '\n' rm

Explanation:

  • ls -t prints all files in the current dir, sorted by modification time, newest first.
  • tail -n +6 ignores the first 5 lines and prints lines 6 onwards.
  • xargs -d '\n' rm removes the files passed to it, one per line. If you are absolutely sure there are no spaces or quotes in the filenames, you can use just xargs rm.

Note this deletes as many files as needed to leave only 5 files in the dir. If you want to delete only the one oldest file, replace +6 with 1.


You could look at set -- /home/backup/databasebk_* and while $# is greater than five, delete a file.

So the code would look similar to

set -- /home/backup/databasebk_*
while [ $# -gt 5 ]
do
  echo "Removing old backup $1"
  rm "$1"
  shift
done

This works because the filenames you picked are automatically in "oldest first" order.

For consistency I would set a variable (I normally call it BASE but you can call it whatever you like)

So

BASE=/home/backup/databasebk_
FILE=${BASE}!`date +"%Y-%m-%d_%H:%M"`.sql
....
set -- ${BASE}*
while [ $# -gt 5 ]
do
  echo "Removing old backup $1"
  rm "$1"
  shift
done

I think a better approach would be to use logrotate, as this application already performs the actions you are trying to achieve with your script. I tested the following scripts on my test server.

  1. Manually backup the database, this is needed because logrotate will not run if the file doesn't exist.
    $ mysqldump -uroot -pmy5trongpass database > mydatabase.sql
    $ ls
    $ mydatabase.sql

Example of error if the first database was not created.

    #**logrotate -f** will force our new rule to run now and backup the database
    #this is for testing purposes.

    $ logrotate -f /etc/logrotate.d/mysql_backup
    error: stat of /home/backups/mydatabase.sql failed: No such file or directory
  1. Create a logrotate file/rule. Here is the one that I created based on other rules locates in /etc/logrotate.d/
    $ cat /etc/logrotate.d/mysql_backup
    /home/backups/mydatabase.sql{
            create 640 root mysql
           daily
            rotate 2
            nocompress
        postrotate
            mysqldump -uroot -pmy5trongpass test > mydatabase.sql;
            echo "done"
        endscript
    }
  1. Test you configuration using
$ logrotate -f /etc/logrotate.d/mysql_backup
$ logrotate -f /etc/logrotate.d/mysql_backup
done
$ ll
total 16
-rw-r-----. 1 root mysql 1261 Feb  3 21:46 mydatabase.sql
-rw-r-----. 1 root mysql 1261 Feb  3 21:44 mydatabase.sql.1
-rw-r-----. 1 root mysql 1261 Feb  3 21:44 mydatabase.sql.2

you will see that a new file will be created followed by a number, this can be changed to show dates by using the following options

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

dateext
Archive old versions of log files adding a daily extension like YYYYMMDD instead of simply adding a number. The extension may be configured using the dateformat option.

dateformat format_string
Specify the extension for dateext using the notation similar to strftime(3) function. Only %Y %m %d and %s specifiers are allowed. The default value is -%Y%m%d. Note that also the character separating log name from the extension is part of the dateformat string. The system clock must be set past Sep 9th 2001 for %s to work correctly. Note that the datestamps generated by this format must be lexically sortable (i.e., first the year, then the month then the day. e.g., 2001/12/01 is ok, but 01/12/2001 is not, since 01/11/2002 would sort lower while it is later). This is because when using the rotate option, logrotate sorts all rotated filenames to find out which logfiles are older and should be removed.