按扩展名编号查找最新文件

按扩展名编号查找最新文件

我想首先在时钟可能被重置的嵌入式系统中自动清理最旧的日志文件(因此文件时间没有用)。我正在寻找一个简单的 shell 脚本来查找最新文件,这样我就知道不应该删除哪些文件。他们遵循这种形式:

LogFileTypeA.log
LogFileTypeA.log.0
LogFileTypeA.log.1
LogFileTypeB.log     <-- this is the latest of Type B
LogFileTypeA.log.2
LogFileTypeC.log 
LogFileTypeC.log.0   <-- this is the latest of Type C
LogFileTypeA.log.3   <-- this is the latest of Type A

我想删除除每种类型中最新的之外的所有内容。有没有一种简单的方法可以使用 shell 脚本查找最新版本?

我正在使用 Bash 版本GNU bash, version 4.4.12(1)-release (sparc-buildroot-linux-gnu),并sort --version显示BusyBox v1.26.2 (2018-05-07 10:50:40 MDT) multi-call binary.

这是一个快速测试......如果您运行此测试来设置场景:

#!/bin/bash
touch typeA.log
touch typeA.log.0
touch typeA.log.1
touch typeA.log.5
touch typeB.log
touch typeB.log.0
touch typeC.log
touch typeD.log.0
touch typeD.log.1
touch typeD.log.2
touch typeD.log.3
touch typeD.log.4
touch typeD.log.5
touch typeD.log.6
touch typeD.log.7
touch typeD.log.8
touch typeD.log.9
touch typeD.log.10
touch typeD.log.11
touch typeD.log.12
touch typeD.log.99
touch typeD.log.100
touch typeD.log.101
touch typeD.log.215
echo A=5
echo B=0
echo C=log
echo D=215

运行解决方案脚本后,您应该退出:

typeA.log.5
typeB.log.0
typeC.log
typeD.log.215

答案1

zsh

typeset -A seen=()
for f (*.log*(nOn)) {((seen[${f%%.*}]++)) && echo rm -f -- $f}

echo(如果对结果满意则删除。

*.log*(nOn)按相反的数字顺序列出*.log*文件(其中,f.log排序在f.log.0其自身之后f.log.9其自身 之后 之后f.log.10)。

typeset -A seen=()声明一个$seen关联数组。如果第一个( )rm之前的部分之前已经见过,我们就将该文件保存。.${f%%.*}

使用任何 shell 和 GNU 实用程序

printf '%s\0' *.log* |
  sort -rzV |
  gawk -v RS='\0' -v ORS='\0' -F. 'seen[$1]++' |
  xargs -r0 echo rm -f --

POSIXly 或使用 busybox 实用程序

但假设文件名不包含空格字符、引号或反斜杠:

printf '%s\n' *.log* |
  sort -rt. -k1,1 -k3,3rn |
  awk -F. 'seen[$1]++' |
  xargs echo rm -f --

所有这些都假设文件名之前的部分.log不包含点。

答案2

在我看来,您想保留按默认词典排序顺序最后排序的文件。

嗯,默认排序顺序不适用于位数可变的数字。但如果数字是连续的,在零和最高值之间没有缺失(就像在原始问题中一样),然后我们可以从零开始计数,直到找到不存在的数字,然后删除除最后一个找到的所有数字:

#!/bin/sh
for group in *.log; do
    i=0
    last="$group"
    while [ -f "$group.$i" ]; do
        rm "$last"
        last="$group.$i"
        i=$((i+1))
    done
    echo "did not remove '$last'"
done

之后删除除,和touch foo.log foo.log.{0..13} bar.log asdf.log asdf.log.0之外的所有内容。foo.log.13bar.logasdf.log.0

相关内容