拡張番号で最新のファイルを探す

拡張番号で最新のファイルを探す

時計をリセットできる組み込みシステムで、最も古いログファイルを最初に自動的にクリーンアップしたいと思います(したがってファイル時間は役に立ちません)。どのファイルを削除してはならないかを知るために、最新のファイルを見つけるための簡単なシェルスクリプトを探しています。彼らは次の形式に従います。

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

各タイプの最新の項目だけを除いてすべてを削除したいと思います。シェルスクリプトを使用して最新バージョンを簡単に見つける方法はありますか?

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.0f.log.9f.log.10

typeset -A seen=()連想配列を宣言します$seen。最初の()rm前の部分が以前に見たことがある場合は、ファイルを保存します。.${f%%.*}

すべてのシェルと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

デフォルトの事前ソート順でファイルを最後にソートしたいようです。

さて、デフォルトのソート順序は、可変数字を持つ数字では機能しません。しかし、数字が連続している場合、0と最も高い値の間に欠けているものがない場合(元の質問のように)、存在しない数字が見つかるまで0から数え始めてから、見つかった最後の数字を除くすべての数字を削除できます。

#!/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.0foo.log.13bar.logasdf.log.0

関連情報