用于计算文件的Shell脚本,然后删除最旧的文件

时间:2010-06-02 17:27:49

标签: linux bash shell

我是shell脚本的新手,所以我需要一些帮助。我有一个填满备份的目录。如果我有10个以上的备份文件,我想删除最旧的文件,这样就可以删除10个最新的备份文件。

到目前为止,我知道如何计算文件,这看起来很容易,但如果计数超过10,我如何删除最旧的文件?

if [ls /backups | wc -l > 10]
    then
        echo "More than 10"
fi

12 个答案:

答案 0 :(得分:85)

试试这个:

ls -t | sed -e '1,10d' | xargs -d '\n' rm

这应该处理文件名中的所有字符(换行符除外)。

这里发生了什么?

  • ls -t按修改时间的降序列出当前目录中的所有文件。即,最近修改的文件是第一个,每行一个文件名。
  • sed -e '1,10d'删除前10行,即10个最新文件。我使用此代替tail,因为我永远不会记得我是否需要tail -n +10tail -n +11
  • xargs -d '\n' rm收集每个输入行(没有终止换行符)并将每行作为参数传递给rm

与此类任何事情一样,请在安全的地方进行实验。

答案 1 :(得分:23)

find是执行此类任务的常用工具:

find ./my_dir -mtime +10 -type f -delete

<强>说明

  • ./my_dir您的目录(替换为您自己的目录)
  • -mtime +10超过10天
  • -type f仅限文件
  • -delete毫不奇怪。 删除它以在执行整个命令之前测试find过滤器

并注意./my_dir存在以避免不良意外!

答案 2 :(得分:12)

执行此类事情的正确方法是使用logrotate

答案 3 :(得分:6)

确保你的pwd是删除文件的正确目录(假设文件名中只有常规字符):

ls -A1t | tail -n +11 | xargs rm

保留最新的10个文件。我用相机程序'motion'来保存最新的帧抓取文件。感谢所有正在进行的答案,因为你告诉我该怎么做。

答案 4 :(得分:3)

我喜欢@Dennis Williamson和@Dale Hagglund的答案。 (每个+1)

以下是使用find(使用-newer测试)与您开始时类似的另一种方法。

这是在cygwin的bash中完成的......

if [[ $(ls /backups | wc -l) > 10 ]]
then
  find /backups ! -newer $(ls -t | sed '11!d') -exec rm {} \;
fi

答案 5 :(得分:2)

直截了当的档案柜台:

max=12
n=0
ls -1t *.dat |
while read file; do
    n=$((n+1))
    if [[ $n -gt $max ]]; then
        rm -f "$file"
    fi
done

答案 6 :(得分:1)

stat -c "%Y %n" * | sort -rn | head -n +10 | \
        cut -d ' ' -f 1 --complement | xargs -d '\n' rm

细分:获取每个文件的最后修改时间(格式为“time filename”),从最旧到最新排序,保留除最后十个条目以外的所有文件,然后保留所有文件但是第一个字段(仅保留文件名部分)。

修改:使用cut代替awk,因为后者并非始终可用

编辑2 :现在处理带空格的文件名

答案 7 :(得分:1)

在非常有限的chroot环境中,我们只有几个程序可用于实现最初的问题。我们这样解决了:

MIN_FILES=5
FILE_COUNT=$(ls -l | grep -c ^d )


if [ $MIN_FILES -lt $FILE_COUNT  ]; then
  while [ $MIN_FILES -lt $FILE_COUNT ]; do
    FILE_COUNT=$[$FILE_COUNT-1]
    FILE_TO_DEL=$(ls -t | tail -n1)
    # be careful with this one
    rm -rf "$FILE_TO_DEL"
  done
fi

<强>解释

  • FILE_COUNT=$(ls -l | grep -c ^d )计算当前文件夹中的所有文件。我们也可以使用wc -l而不是grep,但是没有在该主机上安装wc。
  • FILE_COUNT=$[$FILE_COUNT-1]更新当前的$FILE_COUNT
  • FILE_TO_DEL=$(ls -t | tail -n1)将最旧的文件名保存在$FILE_TO_DEL变量中。 tail -n1返回列表中的最后一个元素。

答案 8 :(得分:1)

我刚刚找到了这个主题,mikecolley的解决方案在第一步中对我有所帮助。由于我需要单行Homematic(Raspberrymatic)脚本的解决方案,因此遇到一个问题,该命令仅给我文件名,而不是“ rm”所需的整个路径。我使用的CUxD Exec命令无法在所选文件夹中启动。

这是我的解决方法:

ls -A1t $(find /media/usb0/backup/ -type f -name homematic-raspi*.sbk) | tail -n +11 | xargs rm

解释:

  • find /media/usb0/backup/ -type f -name homematic-raspi*.sbk仅搜索命名为-type f(区分大小写)或使用-name homematic-raspi*.sbk(不区分大小写)的文件夹-iname /media/usb0/backup/
  • ls -A1t $(...)列出find给出的文件,但不包括以“。”开头的文件。或“ ..” -A按mtime -t排序,仅返回一列-1
  • tail -n +11仅返回最后{strong> 10 -n +11行,以跟随rm
  • xargs rm,最后删除列表中的Raiming文件

也许这可以帮助其他人进行更长的搜索,并使解决方案更加灵活。

答案 9 :(得分:0)

基于其他建议和一些awk foo,我可以使用它。我知道这是一个老话题,但是我在这里找不到合适的答案,因此为我进行了排序。这只会删除最旧的文件,但是您可以将head -n 1更改为10,并获取最旧的文件10。

找到$ DIR -type f -printf'%T +%p \ n'|排序头-n 1 | awk'{first = $ 1; $ 1 =“”;打印$ 0}'| xargs -d'\ n'rm

答案 10 :(得分:-2)

通过stat&amp; amp;使用inode号码find命令(以避免讨厌文本名称问题):

stat -f "%m %i" * | sort -rn -k 1,1 | tail -n +11 | cut -d " " -f 2 | \
   xargs -n 1 -I '{}' find "$(pwd)" -type f -inum '{}' -print

#stat -f "%m %i" * | sort -rn -k 1,1 | tail -n +11 | cut -d " " -f 2 | \
#   xargs -n 1 -I '{}' find "$(pwd)" -type f -inum '{}' -delete 

答案 11 :(得分:-6)

试验一下,因为我不是100%确定它会起作用:

cd /backups; ls -at | tail -n +10 | xargs -I{} "rm '{}'"