How can I find and delete files based on date in a linux shell script without find?
PLEASE NOTE THAT I CANNOT USE ‘find’ IN THE TARGET ENVIRONMENT I need to delete all files more than 7 days old in a linux shell script. SOmething like:
FILES=./path/to/dir for f in $FILES do echo "Processing $f file. " # take action on each file. $f store current file name # perhaps stat each file to get the last modified date and then delete files with date older than today -7 days. done
but discovered that I cannot use find on the target system (there is no permission for the cron user and this can’t be changed). Target system is Redhat Enterprise. The file names are formatted like this: gzip > /mnt/target03/rest-of-path/web/backups/DATABASENAME_ date «+%Y-%m-%d» .gz
4 Answers 4
#!/bin/sh DIR="/path/to/your/files" now=$(date +%s) DAYS=30 for file in "$DIR/"* do if [ $(((`stat $file -c '%Y'`) + (86400 * $DAYS))) -lt $now ] then # process / rm / whatever the file. fi done
A bit of explanation: stat -c ‘%Z’ gives the modification time of the file as seconds since the UNIX epoch for a file, and $(date +%s) gives the current UNIX timestamp. Then there’s just a simple check to see whether the file’s timestamp, plus seven days’ worth of seconds, is greater than the current timestamp.
Thanks — am getting errors about a missing ‘)’. Should $now also be in quotes? I’m putting $(rm «$file») where your comment is.
@pgl Thanks for this awesome script, but it didn’t work on busybox, it needed to be massaged a bit so here is how it worked out form me: #!/bin/sh DIR=»/path/to/your/files» now=$(date +%s) DAYS=30 for file in «$DIR/»* do if [ $((( stat $file -c ‘%Y’ ) + (86400 * $DAYS))) -lt $now ] then # process / rm / whatever the file. fi done
Since you have time in the filename then use that to time the deletion heres some code that does that :
This script gets the current time in seconds since epoch and then calculates the timestamp 7 days ago. Then for each file parses the filename and converts the date embeded in each filename to a timestamp then compares timestamps to determine which files to delete. Using timestamps gets rid of all hassles with working with dates directly (leap year, different days in months, etc )
The actual remove is commented out so you can test the code.
#funciton to get timestamp X days prior to input timestamp # arg1 = number of days past input timestamp # arg2 = timestamp ( e.g. 1324505111 ) seconds past epoch getTimestampDaysInPast () < daysinpast=$1 seconds=$2 while [ $daysinpast -gt 0 ] ; do daysinpast=`expr $daysinpast - 1` seconds=`expr $seconds - 86400` done # make midnight mod=`expr $seconds % 86400` seconds=`expr $seconds - $mod` echo $seconds ># get current time in seconds since epoch getCurrentTime() < echo `date +"%s"` ># parse format and convert time to timestamp # e.g. 2011-12-23 -> 1324505111 # arg1 = filename with date string in format %Y-%m-%d getFileTimestamp () < filename=$1 date=`echo $filename | sed "s/[^0-9\-]*\([0-9\-]*\).*/\1/g"` ts=`date -d $date | date +"%s"` echo $ts >########################### MAIN ############################ # Expect directory where files are to be deleted to be first # arg on commandline. If not provided then use current working # directory FILEDIR=`pwd` if [ $# -gt 0 ] ; then FILEDIR=$1 fi cd $FILEDIR now=`getCurrentTime` mustBeBefore=`getTimestampDaysInPast 7 $now` SAVEIFS=$IFS # need this to loop around spaces with filenames IFS=$(echo -en "\n\b") # for safety change this glob to something more restrictive for f in * ; do filetime=`getFileTimestamp $f` echo "$filetime lt $mustBeBefore" if [ $filetime -lt $mustBeBefore ] ; then # uncomment this when you have tested this on your system echo "rm -f $f" fi done # only need this if you are going to be doing something else IFS=$SAVEIFS
Bash — delete files by date/filename
I have a bash script which creates a mysqldump backup every hour in a certain directory. The filenames of the backup files include the date and hour as per the following schema:
backupfile_30-05-2012_0800.sql.gz backupfile_01-06-2012_0100.sql.gz backupfile_05-06-2012_1500.sql.gz
- Keep alternate hour backups older than a day
- Keep twice daily backups older than a week
- Keep once daily backups older than a month.
I have the following beginnings of the script:
#!/bin/bash cd /backup_dir for file in * do # do the magic to find out if this files time is up (i.e. needs to be deleted) # delete the file done
2 Answers 2
I have seen many fancy scripts like this for taking scheduled backups and wonder why folks don’t make a use of logroate utility available on most of *nix distros available today support following options of your interest:
compress Old versions of log files are compressed with gzip by default. dateext Archive old versions of log files adding a daily extension like YYYYMMDD instead of simply adding a number. olddir directory Logs are moved into directory for rotation. The directory must be on the same physical device as the log file being rotated, and is assumed to be relative to the directory holding the log file unless an absolute path name is specified. When this option is used all old versions of the log end up in directory. This option may be overriden by the noolddir option. notifempty Do not rotate the log if it is empty (this overrides the ifempty option). postrotate/endscript The lines between postrotate and endscript (both of which must appear on lines by themselves) are executed after the log file is rotated. These directives may only appear inside of a log file definition. See prerotate as well.
Best way to delete large amount of files by date
So, I have a folder with alot of files, they are generated by second and need to be kept in I only can delete them after 90 days, so as you may guess, I would generate tons of files and then after the 90 days I’m able to delete those files that is older than 90 days. But, I’m stuck in the part where I search for those files, since I have alot, the system complains that the list is too large and thus I can’t remove them. What is the best solution so I can pass this? The file names are in timestamp mode, so I could start by it, but I want to make sure all files are deleted after some time. I have tried these methods
rm -rf * find /path/to/files/ -type f -name '*.ts' -mtime +90 -exec rm <> \;
I have also managed to create a script to delete by filename, but with this method I have no guarantee that all the files are deleted.
Since I’m still developing this, yesterday I generated about 5 days of files and want to erase them, I just did a rm -rf * and the system yelled at me.
The problem is not only deleting them. think ahead, and create a directory structure YEAR/MONTH/DATE/HOUR automatically, it will be easier to manage.
Please don’t ever do rm -rf * . You should always be as specific as possible when removing files with globbing. rm — ./* would be better for you, no need for -r as you want to remove files not directories, and you should only use -f if you have to.
When you say several methods weren’t effective, please provide more detail. Edit your question to include exactly the command you issued and any error messages or other relevant output produced.
Удаление файлов старше n дней в Linux
Пользователи Linux иногда сталкиваются с ситуацией, когда нужно почистить определенный каталог, удалив из него старые, неиспользуемые файлы. Через стандартный проводник это делать далеко не всегда удобно. Но данную процедуру очень просто выполнять через терминал.
По ходу данной статьи мы разберемся с удалением файлов старше определенного количества дней в Ubuntu. Заодно объясним некоторые нюансы этой процедуры.
Удаление файлов старше n дней в Linux
Для терминала Ubuntu существует специальная команда find, которая отвечает за поиск файлов на компьютере. А с помощью опции -mtime получится найти только те файлы, дата изменения которых старше заданного временного промежутка. В качестве примера возьмем каталог Downloads и срок в 35 дней.
Откройте терминал и запустите следующую команду:
find ~/Downloads -type f -mtime +35
Вам необязательно действовать напрямую и стирать сразу же все файлы. Их можно отсортировать дополнительно по еще одному признаку, например, по названию или расширению. Для этого есть опция -name, которая прописывается сразу же после директории. Если нужно избавиться только от zip-архивов, то подойдет такая команда:
find ~/Downloads -name «*.zip» -type f -mtime +35 -delete
Ну и напоследок хотелось бы упомянуть, что при запуске терминала Ubuntu из конкретной папки вручную директорию прописывать не придется. Это можно сделать через стандартное приложение Файлы, если перейти к нужному каталогу, кликнуть правой клавишей мыши по пустому месту и в контекстном меню выбрать пункт Открыть в терминале.
Тогда команда для поиска, если она еще нужна, сократится до следующего варианта:
А для удаления не забудьте в конце дописать опцию -delete:
Выводы
По ходу данной статьи мы вкратце объяснили, как можно в конкретном каталоге отыскать файлы старше определенного возраста через терминал Ubuntu, а также как удалить файлы старше n дней linux. Сама по себе процедура довольно простая, но может сэкономить много времени при чистке уже ненужных данных с компьютера.
Обнаружили ошибку в тексте? Сообщите мне об этом. Выделите текст с ошибкой и нажмите Ctrl+Enter.