Bash スクリプト: 最新のコピーを保持しながら条件付きで古いファイルを削除する

Bash スクリプト: 最新のコピーを保持しながら条件付きで古いファイルを削除する

注: jeff-schaller からの回答はありますが、 に依存しますzsh。そのため、 に基づいた回答を取得したいと思いますBash

バックアップ ディレクトリから古いファイルを条件付きで削除する Bash スクリプトを作成したいと思います。

2 つの異なるファイル バックアップには 2 つの条件があります。

1、の最新のコピーを保存しEdge_Profile_*.tgz、残りを削除するEdge_Profile_*.tgz 5日以上経過している場合のみ

2、 の最新のコピーを保持しFirefox_Profile_*.tgz、 の残りを削除しますFirefox_Profile_*.tgz年齢は関係ない

AskUbuntu の回答を次のように変更しました:https://askubuntu.com/a/933098/928088

脚本:

#!/bin/bash

LOG_FILE="/home/admn/Cleanup.log"
TEMP_LOG="/tmp/Temp_Cleanup.log"

mv $LOG_FILE $TEMP_LOG

{

cd /home/admn/Downloads/Test;

echo "Cleanup log:" `date`

find /home/admn/Downloads/Test/Edge_Profile_*.tgz -type f \( -mtime +5 -printf 'Y\t' -o -printf 'N\t' \) -printf '%A@\t%p\0' |
    sort -zk2,2 | head -zn -1 | while read -r -d '' flag _ file; do \
        case "$flag" in 
            'Y') echo rm "$file" 
               ;; 
            *) echo "skipping $file (too new)"
               ;; 
        esac;
done

echo

find /home/admn/Downloads/Test/Firefox_Profile_*.tgz -type f \( -printf 'Y\t' -o -printf 'N\t' \) -printf '%A@\t%p\0' |
    sort -zk2,2 | head -zn -1 | while read -r -d '' flag _ file; do \
        case "$flag" in 
            'Y') echo rm "$file" 
               ;; 
            *) echo "skipping $file (too new)"
               ;; 
        esac        
done

} &>> $LOG_FILE

cat $TEMP_LOG >>$LOG_FILE

exit;

ログファイルに次のように出力しますecho:

/usr/local/scripts/cleanup.sh

rm /home/admn/Downloads/Test/Edge_Profile_Jul_06_2021_00-35.tgz
rm /home/admn/Downloads/Test/Edge_Profile_Jul_07_2021_00-35.tgz
....
skipping /home/admn/Downloads/Test/Edge_Profile_Jul_12_2021_00-35.tgz (too new)
skipping /home/admn/Downloads/Test/Edge_Profile_Jul_13_2021_00-35.tgz (too new)
....

rm /home/admn/Downloads/Test/Firefox_Profile_Jul_01_2021_00-35.tgz
rm /home/admn/Downloads/Test/Firefox_Profile_Jul_02_2021_00-35.tgz
....

実際にスクリプトを実行しているときにログファイルに出力しますecho

/home/admn/Downloads/cleanup.sh: line 24: skipping /home/admn/Downloads/Test/Edge_Profile_Jul_12_2021_00-35.tgz (too new): No such file or directory
/home/admn/Downloads/cleanup.sh: line 24: skipping /home/admn/Downloads/Test/Edge_Profile_Jul_13_2021_00-35.tgz (too new): No such file or directory
....

ディレクトリ内のファイル総数: 20 ファイル

1、Edge_Profile_*.tgz: 7月6日から7月17日まで: 12ファイル

2、Firefox_Profile_*.tgz: 7月1日から7月8日まで: 8ファイル

問題:

(1)私考えるスクリプトは一応動作していますが、何が起こっているのかわからないままほとんどの部分を変更したため、確信はありません。

(2)ログファイルへの出力:

echo次のように、ファイル名だけ(フルパスではない)を除いて、で取得したのとまったく同じ出力をログファイルに表示したいです。

rm Edge_Profile_Jul_11_2021_00-35.tgz

skipping Edge_Profile_Jul_12_2021_00-35.tgz (too new)

OS: Ubuntu MATE 21.04

どうもありがとう。

答え1

ファイルの修正日時に基づいてファイルを操作するには、直接アクセスできるシェルを使用すると非常に簡単です。zsh はそのようなシェルの 1 つです。sudo apt install zshインストールするだけです。ファイルは 1 つのディレクトリにあるように見えるため、この回答は非再帰的です。まず、より単純なケースを示します。

  • Firefox_Profile_*.tgz の最新のコピーを保持し、残りを古いものに関係なく削除するには:

    echo would rm -v -- Firefox_Profile_*.tgz(.om[2,-1])
    

    正しいと思われる部分を削除しますecho would。これはglob (ワイルドカード) 修飾子括弧内は次の 3 つのことを行います。

    • プレーンファイルのみ(ディレクトリやソケットなどではない)を選択します。.
    • ファイルを新しいものから古いものへと変更順に並べます。om
    • 結果リストの2番目の要素から最後までのスライスを選択します。最初の(最新の)ファイルはスキップし、[2,-1]

    一致するファイルがない場合、zsh は停止し、「zsh: 一致するファイルが見つかりません」というメッセージを表示し、 を実行しませんrm

  • Edge_Profile_*.tgz の最新のコピーを保持し、5 日以上経過したファイルのみを削除するには、まず最新のものを取得します。

    newest=(Edge_Profile_*.tgz(.om[1]))
    

    ...そして、5日以上経過したものを取得します。

    older=(Edge_Profile_*.tgz(.m+5))
    

    ここでの新しい部分は、修飾子+5の onですm。これにより、5 日以上経過したファイルが選択されます。その後、最新のファイルが削除リストに含まれていないことを確認します。

    remove=("${(@)older:|newest}")
    

    ここでの新しい部分は配列減算記号です:|。これは、zshマニュアルのパラメータ拡張セクション. 「最新」に含まれない「古い」要素を選択します。最後に、そのファイルのリストを削除します。

    echo would rm -v -- "${remove[@]}"
    

関連情報