删除除最新文件以外的所有内容

比方说,我有一个目录ḟoo/其中包含很多文件在某种目录结构。 我需要保留其中一些,但不是全部。

有没有一种方法(就地)删除所有的,除了(说)500最新?

我经常做这个任务,我使用以下的变种。 它是一个pipe道结合各种简单的工具:查找所有文件,预先安排文件修改时间,sorting,删除文件修改时间,显示除500以外的所有行,并删除它们:

 find foo/ -type f | perl -wple 'printf "%12u ", (stat)[9]' | \ sort -r | cut -c14- | tail -n +501 | \ while read file; do rm -f -- "$file"; done 

几点意见:

  • 如果你使用“bash”,你应该使用“读取-r文件”,而不是“读取文件”。

  • 使用“perl”删除文件的速度更快(除了使用“read -r file”之外,还可以更好地处理文件名中的“奇怪”字符):

     ... | tail -n +501 | perl -wnle 'unlink() or warn "$_: unlink failed: $!\n"' 
  • 某些版本的“尾巴”不支持“-n”选项,所以你必须使用“尾巴+501”。 一个便携的方式跳过500第一线是

      ... | perl -wnle 'print if $. > 500' | ... 
  • 如果您的文件名包含换行符,则不起作用。

  • 这是不需要GNU的发现。

结合上述给你:

 find foo/ -type f | perl -wple 'printf "%12u ", (stat)[9]' | \ sort -r | cut -c14- | perl -wnle 'print if $. > 500' | \ perl -wnle 'unlink() or warn "$_: unlink failed: $!\n"' 

这是我将如何在Python 3中执行的,这也适用于其他操作系统。 testing完成后,请确保取消注释实际删除文件的行。

 import os,os.path from collections import defaultdict FILES_TO_KEEP = 500 ROOT_PATH = r'/tmp/' tree = defaultdict(list) # create a dictionary containing file names with their date as the key for root, dirs, files in os.walk(ROOT_PATH): for name in files: fname = os.path.join(root,name) fdate = os.path.getmtime( fname ) tree[fdate].append(fname) # sort this dictionary by date # locate where the newer files (that you want to keep) end count = 0 inorder = sorted(tree.keys(),reverse=True) for key in inorder: count += len(tree[key]) if count >= FILES_TO_KEEP: last_key = key break # now you know where the newer files end, older files begin within the dict # act accordingly for key in inorder: if key < last_key: for f in tree[key]: print("remove ", f) # uncomment this next line to actually remove files #os.remove(f) else: for f in tree[key]: print("keep ", f) 

我不知道“500最新”,但发现你可以删除比X分钟/天更旧的东西。 文件和大于2天的示例:

 find foo/ -mtime +2 -a -type f -exec rm -fv \{\} \; 

先testing一下:

 find foo/ -mtime +2 -a -type f -exec ls -al \{\} \; 

注意“\”之前的反斜杠和空格。 查看查找手册页获取更多信息。

如果你可以保留文件x天/小时,而不是最新的x号码,你可以用tmpwatch --ctime 7d

我认为find命令的-mtime-newer选项对你很有用。 你可以看到man find更多的信息。

为什么不使用这个更简单的代码:

 $ ls -t1 foo/| xargs -d '\n' rm --