ファイル名の日付に基づいて古いバックアップを削除する方法は?

ファイル名の日付に基づいて古いバックアップを削除する方法は?

次の名前の毎日のバックアップがあります。

yyyymmddhhmm.zip // pattern
201503200100.zip // backup from 20. 3. 2015 1:00

3日後にすべてのバックアップを削除するスクリプトを作成しようとしています。さらに、スクリプトはパターンと一致しないフォルダ内の他のすべてのファイルを削除できる必要があります(ただし、無効にするスイッチはスクリプト内にあります)。

ファイルの寿命を確認するために他のプログラムもファイルを操作して改ざんする可能性があるため、バックアップタイムスタンプを使用したくありません。

の助けを借りて:UNIXで5日以上古いファイルを削除する(タイムスタンプではなくファイル名の日付) 私は持っています:

#!/bin/bash

DELETE_OTHERS=yes
BACKUPS_PATH=/mnt/\!ARCHIVE/\!backups/
THRESHOLD=$(date -d "3 days ago" +%Y%m%d%H%M)

ls -1 ${BACKUPS_PATH}????????????.zip |
  while read A DATE B FILE
  do
     [[ $DATE -le $THRESHOLD ]] && rm -v $BACKUPS_PATH$FILE
  done

if [ $DELETE_OTHERS == "yes" ]; then
    rm ${BACKUPS_PATH}*.* // but I don't know how to not-delete the files matching pattern
fi

しかし、続けてこう言います。

rm: missing operand

問題は何ですか?スクリプトを完成させる方法は何ですか?

答え1

コードの最初の問題は次のとおりです。分析するls。つまり、ファイルまたはディレクトリ名にスペースが含まれていると簡単に破損する可能性があります。シェルワイルドカードを使用するか、代わりに使用する必要がありますfind

大きな問題は、データが正しく読み取られないことです。あなたのコード:

ls -1 | while read A DATE B FILE

決して埋められません$FILE。の出力はls -1ファイル名のリストなので、そのファイル名にスペースが含まれていない場合は、read指定した4つの変数の最初の変数のみが入力されます。

以下はスクリプトの作業バージョンです。

#!/usr/bin/env bash

DELETE_OTHERS=yes
BACKUPS_PATH=/mnt/\!ARCHIVE/\!backups
THRESHOLD=$(date -d "3 days ago" +%Y%m%d%H%M)

## Find all files in $BACKUPS_PATH. The -type f means only files
## and the -maxdepth 1 ensures that any files in subdirectories are
## not included. Combined with -print0 (separate file names with \0),
## IFS= (don't break on whitespace), "-d ''" (records end on '\0') , it can
## deal with all file names.
find ${BACKUPS_PATH} -maxdepth 1 -type f -print0  | while IFS= read -d '' -r file
do
    ## Does this file name match the pattern (13 digits, then .zip)?
    if [[ "$(basename "$file")" =~ ^[0-9]{12}.zip$ ]]
    then
        ## Delete the file if it's older than the $THR
        [ "$(basename "$file" .zip)" -le "$THRESHOLD" ] && rm -v -- "$file"
    else
        ## If the file does not match the pattern, delete if 
        ## DELETE_OTHERS is set to "yes"
        [ $DELETE_OTHERS == "yes" ] && rm -v -- "$file"
    fi
done

答え2

FreeBSDで使用されている:例:/usr/home/foobarで5760分(4日)より古いfoobar所有のすべてのファイルを見つけて削除します。

find /usr/home/foobar -user foobar -type f -mmin +5760 -delete

答え3

sedとの間の行を忘れないでください。この行が重要です。ls -1while read

私が提案したい最初の質問は次のとおりです。 (awkの交換に対応するsedが見つかりません。)

ls -1 ${BACKUPS_PATH}????????????.zip |\
  awk -F. '{printf "%s %s\n",$1,$0 ;}' |\
  while read DATE FILE
  do
     [[ $DATE -le $THRESHOLD ]] && rm -v $BACKUPS_PATH$FILE
  done

提供されるシェル操作はテスト用に少なくとも37ビットです$DATE -le $THRESHOLD

関連情報