# Delete files except n files with the “bigger” name?

I want to create a shell script that deletes old release files except last n files. In other words, only mantain last n releases when I deploy a new release.

File names have this format:

appname_releasenumber_date.tar.gz


Maybe there's an easy soluction to do this, but I cannot figure out how to do this.

I've found this solution Cleaner way to delete files on Linux which include a datestamp as part of file name but I need to generate some files first in order to keep the number of files I want to.

• What's the format for the date component in the file names? – iruvar Jun 19 '13 at 14:55
• Are all the files for the same appname in the directory or can they be with different appname? – unxnut Jun 19 '13 at 15:52
• -2012-06-11_14-57-37.tar.gz -> year-month-day_hours-minutes-seconds.tar.gz – Feida Kila Jun 19 '13 at 15:52
• appname is always the same, but thanks anyway I got to the correct answer thanks to salton one – Feida Kila Jun 19 '13 at 16:00

You can search oldest files and then you can check if total number of files are more then N files then delete oldest files first in a script or you can also simply use the following example. Let's say you don't want to delete last 3 latest files:

ls -t1 | tail -n +4 | xargs rm -rf

• This assumes that the modification times are right—may not be the case depending on how the files got there. (E.g., generated from a version control branch will usually have the date it was generated, or possibly even copied to the server, not the date of the most recent change) – derobert Jun 19 '13 at 15:34
• Yes, I assumed that build script generating this release in a directory and no manual copy is taking place. – Raza Jun 19 '13 at 15:40
• i did an order modification and got to the result, thank you very much – Feida Kila Jun 19 '13 at 15:57

I am going to change the answer by @Salton to make it more general:

ls -1 | sort -t_ -n -k2 | head -$((ls | wc -l-1)) | xargs rm -rf  This one sorts on version number and ignores the date completely. So, if an older version has a newer date, the older version will be removed. • quite a pro answer ;) – Feida Kila Jun 19 '13 at 16:06 In zsh, if your versions are in lexicographic order: rm -f appname_*.tar.gz(N[1,-$((n+1))])


The glob qualifier [NUM1,NUM2] retains only the matches from NUM1 to NUM2. With a minus sign, the number counts from the end (-1 is the last match), so [1,-$((n+1))] matches all but the last $n files. The glob qualifier N says that it's ok if there is no match (which happens if there are no more than $n files already). If the versions aren't in lexicographic order, you may need to sort the files in a different order. The glob qualifier n sorts decimal numbers by value, so this will work correctly if you have appname_9_somedate followed by appname_10_someotherdate. rm -f appname_*.tar.gz(nN[1,-$((n+1))])


If you have more complex version numbers, you can specify your own sort function. Write a zsh function version_less that returns 0 if its first argument is less than its second argument, and use

rm -f appname_*.tar.gz(N[1,-$((n+1))]o+version_less)  In any shell, if the order of the files is lexicographic order, you can iterate through the matches. set appname_*.tar.gz while [$# -gt $n ]; do rm "$1"
shift
done


If you need a different order, parsing the output of ls is your best bet. Note that ls mangles non-printable characters in file names, but in your case that shouldn't be a problem.