通过删除旧文件保持文件夹中的文件数量不变

Jis*_*air 4 bash shell-script rm files

我正在尝试创建一个脚本并每 5 分钟在 crontab 中运行它,以便文件夹中的文件数始终保持 50000。如果还有更多,我希望脚本删除旧文件。

#!/bin/bash
LIMIT=500000
NO=0
#Get the number of files, that has `*.pcap` in its name, with last modified time 5 days     ago

NUMBER=$(find /mnt/md0/capture/DCN/ -maxdepth 1 -name "*.pcap" |wc -l)
if [[ $NUMBER -gt $LIMIT ]]  #if number greater than limit
 then
  del=$(($NUMBER-$LIMIT))
   if [ "$del" -lt "$NO" ]
    then
     del=$(($del*-1))
   fi
   echo $del
   FILES=$(
     find /mnt/md0/capture/DCN/ -maxdepth 1 -type f -name "*.pcap" -print0 |
       xargs -0 ls -lt |
       tail -$del |
       awk '{print $8}'
   )
  rm -f ${FILES[@]}
  #delete the originals

 fi
Run Code Online (Sandbox Code Playgroud)

它实际上不起作用,因为文件数量太大而无法运行。有没有其他方法可以完成这项工作?

Sté*_*las 5

对于那些不想对文件名做出假设的人:

zsh

#! /bin/zsh -
keep=5000
rm -f /mnt/md0/capture/DCN/*.pcap(D.om[$((keep+1)),-1])
Run Code Online (Sandbox Code Playgroud)

那是使用zsh通配符限定符:

  • D:包括隐藏文件(d加时赛文件)。
  • .: 仅常规文件(如find's -type f
  • om:反向Ó(基于关于年龄刻申odification时间)
  • [$((keep+1)),-1]:只包括5001 ST到最后。

(如果要删除的文件列表是非常大的,可能会失败,在这种情况下,你可能想使用zargs拆分它,或启用zsh的内置rmzmodload zsh/files)。

使用相对较新版本的 GNU 工具:

cd /mnt/md0/capture/DCN/ &&
  find . -maxdepth 1 -name '*.pcap' -type f -printf '%T@@%p\0' |
    sort -zrn | sed -z "s/[^@]*@//;1,$keep d" | xargs -r0 rm -f
Run Code Online (Sandbox Code Playgroud)

(假设 GNU sed 4.2.2 或更高版本(2012)用于-z,GNU sort1.14 或更高版本(1996)用于-z

find构建一个 NUL 分隔的文件名列表,并带有 Unix 时间戳(如1390682991.0859627500@./file),按 排序sortsed删除时间戳只有从5001打印ST纪录。这作为参数传递给rmusing xargs -r0

或(使用任何版本的 GNU 工具):

cd /mnt/md0/capture/DCN/ &&
  find . -maxdepth 1 -name '*.pcap' -type f -printf '%T@@%p\0' |
    tr '\0\n' '\n\0' | sort -rn | tail -n "+$(($keep+1))" |
    cut -d @ -f2- | tr  '\0\n' '\n\0' | xargs -r0 rm -f
Run Code Online (Sandbox Code Playgroud)

相同,除了我们使用cut删除时间戳并tail选择从 5001 开始的行。因为 GNUcuttail不支持-z处理 NUL 分隔的记录,我们使用tr在输入之前和之后交换换行符和 NUL 字符数据给他们。

使用 GNU ls(4.0(1998)或更高版本),以及bash

shopt -s dotglob
cd /mnt/md0/capture/DCN/ &&
  eval "files=($(ls -dt --quoting-style=shell-always -- *.pcap))" &&
  rm -f -- "${files[@]:$keep}"
Run Code Online (Sandbox Code Playgroud)

(如果文件列表很大,这也可能会失败。另请注意,它可能包含非常规的 pcap 文件(否-type f))。

标准/POSIXly/便携,这要棘手得多:

cd /mnt/md0/capture/DCN/ &&
  ls -dt ./.pcap ./.*.pcap ./*.pcap | awk -v keep="$keep" '
    function process() {
      if (++n > keep) {
        gsub(/[ \t\n"\\'\'']/,"\\\\&", file)
        print file
        file = ""
      }
    }
    /\// {
      if (NR > 1) process()
      file=$0
      next
    }
    {file = file "\n" $0}
    END {if (NR > 0) process()}' | xargs rm -f
Run Code Online (Sandbox Code Playgroud)

(同样,您可能会达到参数数量的限制,并且它不会检查常规文件)。

棘手的一点是用换行符处理文件名。以上,我们传递./*ls该装置/ 将包括一次为每个文件名,我们使用,在awk识别上线每个文件名开始,我们就知道这换行符(除了所有其他的人特xargs)到逃跑xargs