LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   rm by date (https://www.linuxquestions.org/questions/programming-9/rm-by-date-664415/)

investmentbnker75 08-21-2008 02:40 PM

rm by date
 
Guys,

Im stumped on 1 last line of a script im writing, i need to have the script go into each directory called test* and rm anything older than 18 days from the day its executed. Cron will run it daily.

Heres what i have except what will determine the old than 18 days for removal. Sorry im a newb. Thanks!


#!/bin/bash

for i in test01 test02 test03 test04 test05 test06 test07 test08 test09 test10 test11 test12 ; do
rm -rf anything older than 30 days
done

matthewg42 08-21-2008 02:57 PM

Use find to identify files with an mtime older than 30 days and then feed the identified files to rm with xargs:
Code:

find . -name 'test*' -mtime +30 -type f -print0 |xargs -0 rm -f

investmentbnker75 08-21-2008 03:19 PM

Thanks Matthew! So it should look like:

#!/bin/bash

for i in test01 test02 test03 test04 test05 test06 test07 test08 test09 test10 test11 test12 ; do
find . -name 'file*' -mtime +10 -type f -print0 | xargs -0 rm -rf
done

File equals:

file_backup_backup14_20080106.tgz
file_backup_backup14_20080107.tgz
etc...

raconteur 08-21-2008 03:55 PM

You don't really need xargs or the for loop (and the -type parameter, while probably good practice, isn't strictly necessary either if you are sure these files are all regular files)...

Code:

find . -name "file_backup*" -print -type f -mtime +10 -exec rm -f {} \;

bos.beemer 08-21-2008 04:40 PM

I think the xargs approach is faster because it supplies all the arguments to rm that applies to all the files at once. However using -exec will supply the arguments one at a time and thus a bit slow. Besides I don't think you need -print0 either.

find . -name 'test*' -mtime +30 -type f |xargs -0 rm -f

matthewg42 08-21-2008 05:22 PM

With the xargs method, you don't need to use the "for i in ... do ... done", just the single line I provided should do it. The only thing you might have to watch for is that find will recurse into sub-directories, and that the pattern passed to -name is specific enough to only get the files you want.

As a test to see if it is going to operate on the right files, do this first:
Code:

find . -name 'test*' -mtime +30 -type f -print0 |xargs -0 ls -l
If that lists only the files you want to delete, replace the "ls -l" with "rm -f".

investmentbnker75 08-22-2008 12:29 PM

Thanks again Matthew, I wanted to try a variation of this, if it is possible. I would like to take files for the past two months and have a script that will keep the past two weeks and then every Sunday only. Is that possible?

kenoshi 08-22-2008 12:40 PM

I thought using xargs is faster due to the fact that using -exec will fork a child of find for every argument, whereas xargs simply passes the argument to the resulting command?

matthewg42 08-22-2008 02:17 PM

Quote:

Originally Posted by investmentbnker75 (Post 3256193)
Thanks again Matthew, I wanted to try a variation of this, if it is possible. I would like to take files for the past two months and have a script that will keep the past two weeks and then every Sunday only. Is that possible?

Not with the -mtime option to find. If you want such complex behavior, you will probably want to write a perl script or something like that.

*edit* actually you might be able to do it with the printf option, and the -mtime option, ORed together with -o.

raconteur 08-22-2008 03:11 PM

Actually this would be pretty simple to do in the shell if you're using GNU versions of 'ls'.

Code:

ls -l --time-style=+%a
will display the weekday of the modification time on the files.

There are other formats for the style (man ls for specifics, and man date for the formats)

Using that info and the find commands listed above you can construct a simple shell script to do what you want.

investmentbnker75 08-22-2008 03:29 PM

Matthew/Raconteur,

Thanks for the response, but i am confused what the line in the script would be to remove all files but for the last 2 weeks and every Sunday for a two month period. Could you post an example? Thanks a million for the time and the help!

raconteur 08-22-2008 05:11 PM

This is quick and dirty, and only cursorily tested, the usual caveats apply. If I were writing this for keepsies I'd probably do a few things differently.

Change the initial file pattern to match whatever your files are named. I called it filter.sh but of course you can name it whatever you wish...

Remove the sharps if you want a very verbose version.

Code:

#!/bin/bash

for file in `find . -name "backup*" -print`; do
# echo "filter is examining $file"
  older_than_two_months=`find . -wholename $file -mtime +60 -print`
  if [ -n "$older_than_two_months" ]; then
#  echo "filter found that $file is older than two months, deleting"
    rm -f $file
  else
    older_than_two_weeks=`find . -wholename $file -mtime +14 -print`
    if [ -n "$older_than_two_weeks" ]; then
#    echo "filter found that $file is older than two weeks"
      sunday=`ls -l --time-style=+%a $file | awk '{print $6}'`
      if [ "$sunday" != "Sun" ]; then
#      echo "filter found that $file was not modified on a Sunday, deleting"
        rm -f $file
#    else
#      echo "filter found that $file was modified on Sunday, ignoring"
      fi
#  else
#    echo "filter found that $file is newer than two weeks"
    fi
  fi
done

hth

matthewg42 08-22-2008 05:46 PM

Do you want to descend into sub-directories, or just remove files from one directory?

raconteur 08-22-2008 05:54 PM

Quote:

Originally Posted by matthewg42 (Post 3256479)
Do you want to descend into sub-directories, or just remove files from one directory?

Good point, my stab at this assumes one directory.
However, I think if you added a -type f parameter to the initial find it would pass the multi-level test.

matthewg42 08-22-2008 06:15 PM

OK, if you want to descend into sub-directories as well as working in the current directory, here's the command for you:
Code:

find . -type f -mtime +14 -printf "%Cw %p\n" | grep -v ^0 | cut -c3- | xargs rm -f
Please backup before doing this - I take no responsibility if it deletes the wrong files because I might have mis-interpreted your needs or made a mistake.

It is probably a good idea to run it without the "| xargs rm -f" on the end first and verifiy that the files it lists are indeed the ones you want to delete, and only the ones you want to delete. i.e.
Code:

find . -type f -mtime +14 -printf "%Cw %p\n" | grep -v ^0 | cut -c3-
OK, now for an explanation.

The -printf option to find can be used to print more information that the default (which is just to print the file path & name. In this case I used the format string "%Cw %p\n". Please look at the find manual page and find %C. If you read this section of the page, you should be able to see that "%Cw" means the day of week number (0-6) the file was last modified. (0 is Sunday). I could also have used %Ca which would print the day of week like "Sun", "Mon" and so on, but this is locale dependent, so it would not work on a machine with German language settings for example.

The next bit, "%p\n" just means the file path & name with a new line character after it.

The "-mtime +14" means to print only files older than 14 days since the last modification.

The "-type f" means to only print files.

The "." as the first option to find means "start in the current directory".

In you run the find command without the following pipeline, you will see something like this:

Code:

0 ./file1
3 ./file2
6 ./bob/file3

The number is the weekday of modification of the file (0=Sun, 3=Wed, 6=Sat), then the file name in question.

We do not want to delete files which were modified on a Sunday, so we exclude the lines beginning with 0 with the next part of the pipeline:
Code:

grep -v ^0
If the example output of the find command above is what you get, after the grep part, it will look like
Code:

3 ./file2
6 ./bob/file3

The next part of the pipeline:
Code:

cut -c3-
...prints only characters from column 3 onwards - it cuts off the day of week and the space. We now have just a list of files which we want to remove:
Code:

3 ./file2
6 ./bob/file3

This is the input to xargs which calls the specified command (rm -f) for groups of strings read from standard input - i.e. remove the listed files.

I hope that is clear. If you have further questions about it, feel free to ask.


All times are GMT -5. The time now is 06:28 AM.