8

I'm looking for a Bash script that will go into a list of directories and delete all but the four most recently created files.

How can I do this?

3
  • How recent is recent? Is it a predefined time period?
    – bahamat
    Aug 16, 2011 at 4:20
  • Do you want the script to keep the four most recent files as per the whole list of directories or individually for each directory? Also, do you want it to operate recursively?
    – wnrph
    Sep 16, 2011 at 8:41
  • i want the rm command to go into each and every folder and delete all but 4 (of the latest files)
    – Marv1n
    Sep 17, 2011 at 10:48

5 Answers 5

8
ls -t | sed '1,4d' | xargs echo rm

Remove the echo when you're satisfied that's the result you want.

If you have filenames with spaces, more work is required.

4
  • hey mate, ran this command but it just listed the directory names
    – Marv1n
    Aug 16, 2011 at 4:15
  • 3
    We can replace sed '1,4d' with tail -n +5.
    – jfg956
    Aug 16, 2011 at 10:28
  • @Marvin, do you have any aliases, such as for ls? Aug 16, 2011 at 11:20
  • 1
    @Marvin: remove the echo as explained in the answer. Oct 1, 2011 at 23:38
0

Do you want to keep the four most recent files in each directory, or the four most recent files in ANY directory?

To solve the first problem, you would use find to list each directory, then in each, remove all but the four most recent files. This isn't too hard.

To solve the second problem takes a bit more thought, but is actually easier to write.

Basically, find every file recursively. Call the "stat" command returning the file's modification time and name. Sort this descending numerically, and skip the first four files, which are the most recent.

Then remove the leading timestamps, and remove the resulting list of filenames.

Something like (untested):

#!/bin/bash

find "$@" -type f -print0 \
| xargs -0 stat -c$'%Y\t%n' \
| sort -rn \
| awk -F$'\t' 'NR > 4 {print $2}' \
| while read f; do
    echo rm -v "${f}"
  done

This should work, though you'll want to remove the 'echo' in the while loop to make it effective. Test it carefully first!

2
  • Thanks for the reply! I want to keep 4 most recent files in each directory. Basically it's a backups folder for various websites I manage. Each folder is a website. I've got a daily backup script that rips each site (including the db) into a neat little jpa file.
    – Marv1n
    Aug 19, 2011 at 5:23
  • hey mate, i've ran this script but it managed to delete most of the files in each subfolder for extra info i've got the script in /backup/ and the rest of the folder is as shown /backup/website1/file1 /backup/website1/file2 /backup/website1/file3 /backup/website2/file1 /backup/website2/file2 /backup/website2/file3 /backup/website2/file4 and so on and so on
    – Marv1n
    Aug 30, 2011 at 1:55
0

I realise this isn't quite what you're asking, but for this kind of backup I prefer to rotate the log files before creating the new one. It's a bit more explicit, and much simpler to code, like this:

#!/bin/bash

#Archive old backups
move () {
  if [ -e $1 ]
  then
    echo "Archiving old backups: $1 to $2"
    mv -f $1 $2 || echo "FAILED"
  fi
}

#Bump each backup +1
rm -rf backup.4
move backup.3.tgz backup.4.tgz
move backup.2.tgz backup.3.tgz
move backup.1.tgz backup.2.tgz
move backup.tgz backup.1.tgz

#Now create today's backup
...
0

This command should work

find PATH1 PATH2 PATH3 -type f  -printf '%T@ %p\n'|sort -nr|tail -n+5|cut -f 2- -d " "|xargs -i rm {}

If you don't want the command to delete files recursively, add the option -maxdepth 1 before -type f

The command recursively prints each file with its last modification date (find PATH1 PATH2 PATH3 -type f -printf '%T@ %p\n'), then sorts the list by date (sort -nr), then skips the first four entries (tail -n+5). Finally, the time information is stipped off (cut -f 2- -d " ") and the result subsequently passed to xargs which generates and executes the corresponding rm command.

0

The most simplest method:

for d in dir1 dir2 dir3; do
  rm -vf `ls -1t $d | head -n-4` 
done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .