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 '|' -
)

したがって、GNUdateと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日を過ぎたファイルは削除されますが、1ヶ月以内の最後のファイルの場合は削除されません。

例のファイルリストは、方法が重要なので気にしません。方法を知ると、入力を調整できます。

ランダムな日付のリストが与えられると、次のようになります。

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日より古い日付が印刷され除外されます。最後の蛾記入。短くて甘い。完璧。

専門家が指摘したように、上記のすべての作業を1行で実行できます。うわー!

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

関連情報