확장번호로 최신 파일 찾기

확장번호로 최신 파일 찾기

시계가 재설정될 수 있는 임베디드 시스템에서 가장 오래된 로그 파일을 먼저 자동으로 정리하고 싶습니다(따라서 파일 시간은 쓸모가 없습니다). 어떤 파일을 삭제하면 안 되는지 알 수 있도록 최신 파일을 찾기 위한 간단한 쉘 스크립트를 찾고 있습니다. 그들은 다음과 같은 형식을 따릅니다.

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

관련 정보