Delete all but the most recent X files in bash

2019-01-01 06:46发布

Is there a simple way, in a pretty standard UNIX environment with bash, to run a command to delete all but the most recent X files from a directory?

To give a bit more of a concrete example, imagine some cron job writing out a file (say, a log file or a tar-ed up backup) to a directory every hour. I'd like a way to have another cron job running which would remove the oldest files in that directory until there are less than, say, 5.

And just to be clear, there's only one file present, it should never be deleted.

17条回答
若你有天会懂
2楼-- · 2019-01-01 06:55

found interesting cmd in Sed-Onliners - Delete last 3 lines - fnd it perfect for another way to skin the cat (okay not) but idea:

 #!/bin/bash
 # sed cmd chng #2 to value file wish to retain

 cd /opt/depot 

 ls -1 MyMintFiles*.zip > BigList
 sed -n -e :a -e '1,2!{P;N;D;};N;ba' BigList > DeList

 for i in `cat DeList` 
 do 
 echo "Deleted $i" 
 rm -f $i  
 #echo "File(s) gonzo " 
 #read junk 
 done 
 exit 0
查看更多
流年柔荑漫光年
3楼-- · 2019-01-01 06:56

With zsh

Assuming you don't care about present directories and you will not have more than 999 files (choose a bigger number if you want, or create a while loop).

[ 6 -le `ls *(.)|wc -l` ] && rm *(.om[6,999])

In *(.om[6,999]), the . means files, the o means sort order up, the m means by date of modification (put a for access time or c for inode change), the [6,999] chooses a range of file, so doesn't rm the 5 first.

查看更多
时光乱了年华
4楼-- · 2019-01-01 06:56

Removes all but the 10 latest (most recents) files

ls -t1 | head -n $(echo $(ls -1 | wc -l) - 10 | bc) | xargs rm

If less than 10 files no file is removed and you will have : error head: illegal line count -- 0

To count files with bash

查看更多
浅入江南
5楼-- · 2019-01-01 06:58
(ls -t|head -n 5;ls)|sort|uniq -u|xargs rm

This version supports names with spaces:

(ls -t|head -n 5;ls)|sort|uniq -u|sed -e 's,.*,"&",g'|xargs rm
查看更多
怪性笑人.
6楼-- · 2019-01-01 06:59

All these answers fail when there are directories in the current directory. Here's something that works:

find . -maxdepth 1 -type f | xargs -x ls -t | awk 'NR>5' | xargs -L1 rm

This:

  1. works when there are directories in the current directory

  2. tries to remove each file even if the previous one couldn't be removed (due to permissions, etc.)

  3. fails safe when the number of files in the current directory is excessive and xargs would normally screw you over (the -x)

  4. doesn't cater for spaces in filenames (perhaps you're using the wrong OS?)

查看更多
皆成旧梦
7楼-- · 2019-01-01 07:01
leaveCount=5
fileCount=$(ls -1 *.log | wc -l)
tailCount=$((fileCount - leaveCount))

# avoid negative tail argument
[[ $tailCount < 0 ]] && tailCount=0

ls -t *.log | tail -$tailCount | xargs rm -f
查看更多
登录 后发表回答