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:


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"

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.