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?
Super User is a question and answer site for computer enthusiasts and power users. It only takes a minute to sign up.
Sign up to join this communityI'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?
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.
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!
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
...
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.
The most simplest method:
for d in dir1 dir2 dir3; do
rm -vf `ls -1t $d | head -n-4`
done