delete 1 month-old files except when if only a number of files are left
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
delete 1 month-old files except when if only a number of files are left
I'm doing a daily backup for a mysql database and once a month I delete all files that are older than a month. So there are about 30-31 files per month, and double that, the moment I run the clean-up command.
Code:
if [ $(ls /path/to/dir/mysql* | wc -l) -lt 31 ]; then
echo "There are too few files. Not proceeding." && exit 2
else
find /path/to/dir/ -name "mysql*" -mtime +30 -exec rm rf {} \;
fi
Is there a better, cleaner and safer way to do this than using wc to count the backup files?
I would say that solution for the very custom decision you've reached is fine. However, I feel that older files no matter how many of them are either worthless or they are not depending upon the age. Therefore I might lend towards solely the line in your else clause and leave it at that. I'm sure you have your reasons for wishing to retain some small number of files.
Are you creating daily backups? There are many ways to delete old files. How do you run your script? How are your files named?
One method would be to label your backup files as date_mysql_backup where the date could be the current month i.e. 05_xyx_mysql_backup. Create a cron job to delete your scripts on the 1st day of the month.
Do you care about keeping just a months worth of backups or an entire month as defined by the days of the month (1-31). If just the past 31 days of backups regardless of the exact day then run a cron script everyday.
Most do not understand that with ASCII sorting labeling files using the date-name (YYYYMMDD-name) is easier to script and automatically sorts versus name-MMDDYYYY.
I supposed a real other way to contend with this is to use logrotate and specify the age and number of files limits for rotation, along with the number of backups intended to be kept. Plus you can zip the backups so that the results will be smaller, assuming they are text files in the first place. Logrotate is not just for system logs, it also does not have to be for files ending in .log, it can be for any directory, any file extension, or even no extension, it is that flexible.
I'm doing a daily backup for a mysql database and once a month I delete all files that are older than a month. So there are about 30-31 files per month, and double that, the moment I run the clean-up command.
Code:
if [ $(ls /path/to/dir/mysql* | wc -l) -lt 31 ]; then
echo "There are too few files. Not proceeding." && exit 2
else
find /path/to/dir/ -name "mysql*" -mtime +30 -exec rm rf {} \;
fi
Is there a better, cleaner and safer way to do this than using wc to count the backup files?
Thanks
You are deleting files and directories that are older than 30 days. ls is okay, but a shell builtin is elegant+efficient
Code:
argcnt(){ echo $#; }
if [ $(argcnt /path/to/dir/mysql*) -lt 31 ]
then
echo "There are too few files. Not proceeding." && exit 2
else
find /path/to/dir/ -maxdepth 1 -type f -name "mysql*" -mtime +30 -delete
fi
As was stated already, in most practical cases (one file per day is produced) the find statement is sufficient.
@michaelk So I guess my naming method is name-YYYYMMDD, which is neither. But your point is that, besides the format, the date should stand in front of the name.
So given this, the find command actually looks for my_db* (not mysql, as state initially - I simply showed how I did it in my first post, wasn't entirely accurate in this respect)
I'll have a look at logrotate. It seems logic to make use of a system which is already in place in linux. It's just that I don't have lots of experience with logrotate and sometimes I feel it's a little bit daunting, not sure why. It doesn't seem that hard to understand
@MadeInGermany
I don't understand exactly how your function works. How does the number of position parameters ($#) gives the number of files in this context exactly? Can you use $# to count the number of files without using a function, just for the sake of demonstration?
The shell looks into the file system and expands /path/to/dir/mysql* to words.
The function is run with them as arguments. They are mapped to positional parameters within the function (these are indeed local to the function, not overwriting the positional parameters in the main script).
There might be a way to count words without using a function - but I don't know a good one.
Please remind me, what does -- stand for in this context?
From the bash manual page, the function "set" under the section "shell builtin commands"
-- If no arguments follow this option, then the positional
parameters are unset. Otherwise, the positional parame‐
ters are set to the args, even if some of them begin
with a -.
See the manual about what + and - do for each parameter
The -- option means it is the last option. In the case of
set -- $var
and $var being "-brave world" the set command should not see options -b -r -a -v -e
Here we know that the arguments start with / so we can omit the --
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.