90일이 지난 파일은 삭제해야 함(월 말일 제외)

90일이 지난 파일은 삭제해야 함(월 말일 제외)

Unix 디렉토리에서 90일보다 오래된 파일을 제거하는 데 도움이 필요하지만 월말 날짜에 속하는 파일을 유지해야 합니다. (예: 2022년 2월 28일, 3월 31일, 4월 30일) 예:

내 디렉토리에 파일이 있습니다: /usr/home :

  1. ABC.txt.20220529 2022-05-30
  2. ABC.txt.20220530 2022-05-31
  3. ABC.txt.20220531 2022-06-01
  4. ABC.txt.20220601 2022-06-02

6월 1일부터 91일째에 스크립트를 실행하면 1개가 삭제되고 2/3/4는 삭제되지 않아야 합니다. 쉘 스크립트나 Python 스크립트가 필요합니다.

답변1

이것이 고려하려는 파일 이름 끝에 있는 날짜( 20220531in ABC.txt.20220531) 라고 가정하면 zsh다음과 같이 할 수 있습니다.

#! /bin/zsh -
zmodload zsh/datetime
day=86400
strftime -s range '<19700101-%Y%m%d>' $(( EPOCHSECONDS - 91 * day ))
not_last() {
  local t
  TZ=UTC0 strftime -rs t %Y%m%d $REPLY:e &&
    TZ=UTC0 strftime -s t %d $(( t + day )) &&
    (( t != 1 ))
}
echo rm -f -- **/*.txt.$~range(-.+not_last)

마지막으로 수정된 시간인 경우:

#! /bin/zsh -
zmodload zsh/datetime
zmodload zsh/stat
day=86400
not_last() {
  local t
  stat -A t +mtime -- $REPLY &&
    strftime -s t %d $(( t + day )) &&
    (( t != 1 ))
}
echo rm -f -- **/*.txt.*(-.m+90+not_last)

매월 1일이나 말일에 DST가 변경되면 다음 날 계산에 영향을 미칠 가능성이 높습니다.

파일 유형과 mtime을 고려하십시오.뒤쪽에심볼릭 링크 해결. 심볼릭 링크를 무시하려면 -glob 한정자를 제거하세요. D숨겨진 파일도 고려하려면 한정자를 추가하세요 . **/하위 디렉터리의 파일을 고려하지 않으려면 해당 파일을 삭제하세요.

echo결과가 만족스러우면 삭제(테스트 실행)하세요.

의 선택 파일 m+90이 91일 이상인 것처럼 90일 이상의 파일로 변경 하세요 .find-mtime +90m+89

답변2

월의 마지막 날은 0131, 0331, 0430...1231 및 0229(이배 육분위 연도) 및 0228(기타 연도)로 끝나는 연도에 해당됩니다.

GNU 와 -style 중괄호 확장을 date지원하는 셸을 사용하면 1970년부터 2099년 2월까지의 마지막 날짜 목록을 얻을 수 있습니다. 예를 들면 다음과 같습니다.zsh{x..y}

printf '%s\n' {1970..2099}'-03-01 -1 day' | date -uf- +%Y%m%d

따라서 다음 날짜와 일치하는 확장 정규식을 작성할 수 있습니다.

regexp=$(
  {
    printf '%s\n' {0{1,3,5,7,8},10,12}31 {04,06,09,11}30
    printf '%s\n' {1970..2099}'-03-01 -1 day' | date -uf- '+%Y%m%d'
  } | paste -sd '|' -
)

따라서 GNU date와 NUL을 레코드 구분 기호 awk로 지원하는 구현을 사용하면 다음과 같습니다 .RS

LC_ALL=C find . -name '*.txt.[0-9]*' -print0 |
  LC_ALL=C awk -F. -v 'RS=\0' \
                   -v 'ORS=\0' \
                   -v regexp="($regexp)\$" \
                   -v cutoff="$(date -d '90 days ago' +%Y%m%d)" '
    /txt\.[0-9]{8}$/ && $NF < cutoff && $NF !~ regexp' |
  xargs -r0 echo rm -f

또는 파일 이름 끝에 있는 날짜 대신 파일의 마지막 수정 시간을 일치시키려면 GNU는 다음과 같이 이를 구현합니다 find.

LC_ALL=C find . -regextype posix-extended \
                -regex '.*\.txt\.[0-9]{8}' \
                -mtime +90 \
                -printf '%TY%Tm%Td-%p\0' |
  LC_ALL=C awk -v 'RS=\0' \
               -v 'ORS=\0' \
               -v regexp="^[0-9]*($regexp)-" '
    $0 !~ regexp {print substr($0, 10)}' |
  xargs -r0 echo rm -f

동일한 접근 방식을 사용하여 이와 일치하는 zsh glob 패턴을 구성할 수 있습니다.

#! /bin/zsh -
zmodload zsh/datetime
set -o extendedglob
day=86400

start=19700101
strftime -s end %Y%m%d $(( EPOCHSECONDS - 91 * day ))
range="<$start-$end>"

list=({0{1,3,5,7,8},10,12}31 {04,06,09,11}30)

for ((y = $start[1,4]; y <= $end[1,4]; y++)) {
  TZ=UTC0 strftime -rs t %Y%m%d ${y}0301 &&
    TZ=UTC0 strftime -s d %Y%m%d $(( t - day )) &&
    list+=($d)
}
endofmonth="*(${(j[|])list})"

echo rm -f -- **/*.txt.($~range~$~endofmonth)

답변3

다른 답변이 마음에 들지만 더 간단한 솔루션이 있습니다. 또한 원래 질문에서는 지난 달(날짜) 파일이 항상 존재한다고 가정합니다. 하지만 우리 모두는 매월 마지막 날의 스냅샷을 항상 갖고 있지는 않다는 것을 알고 있습니다.

나는 질문을 약간 수정하여 이에 대답하고 있습니다.

  1. 반드시 31일, 30일, 28일일 필요는 없지만 매월 마지막 파일을 보관하세요.
  2. 0~90일 동안의 파일 보관
  3. 90일이 지난 파일은 삭제되지만, 한 달 이내의 마지막 파일인 경우에는 삭제되지 않습니다.

예제의 파일 목록은 방법이 중요하기 때문에 신경쓰지 않습니다. 방법을 알면 입력을 조정할 수 있습니다.

무작위 날짜 목록이 주어지면 다음과 같습니다.

function dates() { echo 2022-12-{06..12}  2022-{01,03,05}-{00..31} 2022-02-{00..28} 2022-{04,06}-{01..30}   2022-12-{01..06} 2022-10-{01..03}| tr ' ' \\n;  }

이 목록에는 모든 날짜가 1월부터 6월까지 표시되며, 12월에는 12일만 나열되고 10월에는 3일만 나열됩니다.

마지막 날을 찾기 위해전시하다매월 목록 내에서 목록을 오름차순으로 정렬한 다음 매월 "가장 오래된" 날짜를 기억합니다. 이것은지난 달.

$ dates | sort \
  | awk -F- '{ lom[$1$2]=$1"-"$2"-"$3 } END { for (i in lom) { print lom[i]} }' \
  | tee /tmp/lom  
2022-01-31
2022-02-28
2022-03-31
2022-04-30
2022-05-31
2022-06-30
2022-10-03
2022-12-12

나는 실제 IT 문제에서 달력 날짜에 관심이 없습니다. 실제로 존재하는 파일에 관심이 있습니다. 12일이 12월의 마지막 스냅샷이고 그날 시스템이 다운되어 31일이 없다면 12일을 유지하고 싶습니다.

이제 우리는 무엇을 알고 있습니까?삭제하지 마세요. 또 다른 부분은 90일이 넘었습니다.

dates | awk -v cutoff=$(date +%Y-%m-%d -d 'today -90 days') \
            '{ if ($1 < cutoff) { print $1 } }'  \
      | grep -v -f /tmp/lom

그러면 90일보다 오래된 날짜가 인쇄되고 제외됩니다.마지막 나방기입. 짧고 달다. 완벽한.

전문가가 지적했듯이 위의 모든 작업을 한 줄로 수행할 수 있습니다. 우와!

dates | sort -r | awk -v cutoff=$(date +%F -d '-90 days') -F- '$0 < cutoff && seen[$1$2]++'

지울 결과 날짜 목록에는 다음이 포함됩니다.

2022-01-00  2022-03-11  2022-05-22  2022-04-05
2022-01-01  2022-03-12  2022-05-23  2022-04-06
2022-01-02  2022-03-13  2022-05-24  2022-04-07
2022-01-03  2022-03-14  2022-05-25  2022-04-08
2022-01-04  2022-03-15  2022-05-26  2022-04-09
2022-01-05  2022-03-16  2022-05-27  2022-04-10
2022-01-06  2022-03-17  2022-05-28  2022-04-11
2022-01-07  2022-03-18  2022-05-29  2022-04-12
2022-01-08  2022-03-19  2022-05-30  2022-04-13
2022-01-09  2022-03-20  2022-02-00  2022-04-14
2022-01-10  2022-03-21  2022-02-01  2022-04-15
2022-01-11  2022-03-22  2022-02-02  2022-04-16
2022-01-12  2022-03-23  2022-02-03  2022-04-17
2022-01-13  2022-03-24  2022-02-04  2022-04-18
2022-01-14  2022-03-25  2022-02-05  2022-04-19
2022-01-15  2022-03-26  2022-02-06  2022-04-20
2022-01-16  2022-03-27  2022-02-07  2022-04-21
2022-01-17  2022-03-28  2022-02-08  2022-04-22
2022-01-18  2022-03-29  2022-02-09  2022-04-23
2022-01-19  2022-03-30  2022-02-10  2022-04-24
2022-01-20  2022-05-00  2022-02-11  2022-04-25
2022-01-21  2022-05-01  2022-02-12  2022-04-26
2022-01-22  2022-05-02  2022-02-13  2022-04-27
2022-01-23  2022-05-03  2022-02-14  2022-04-28
2022-01-24  2022-05-04  2022-02-15  2022-04-29
2022-01-25  2022-05-05  2022-02-16  2022-06-00
2022-01-26  2022-05-06  2022-02-17  2022-06-01
2022-01-27  2022-05-07  2022-02-18  2022-06-02
2022-01-28  2022-05-08  2022-02-19  2022-06-03
2022-01-29  2022-05-09  2022-02-20  2022-06-04
2022-01-30  2022-05-10  2022-02-21  2022-06-05
2022-03-00  2022-05-11  2022-02-22  2022-06-06
2022-03-01  2022-05-12  2022-02-23  2022-06-07
2022-03-02  2022-05-13  2022-02-24  2022-06-08
2022-03-03  2022-05-14  2022-02-25  2022-06-09
2022-03-04  2022-05-15  2022-02-26  2022-06-10
2022-03-05  2022-05-16  2022-02-27  2022-06-11
2022-03-06  2022-05-17  2022-04-00  2022-06-12
2022-03-07  2022-05-18  2022-04-01  2022-06-13
2022-03-08  2022-05-19  2022-04-02  2022-06-14
2022-03-09  2022-05-20  2022-04-03  2022-06-15
2022-03-10  2022-05-21  2022-04-04  2022-06-16

관련 정보