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