Unixで60以上のファイルを含むフォルダ内のファイルを削除するには?

Unixで60以上のファイルを含むフォルダ内のファイルを削除するには?

特定の時間に実行されるcronjobにスクリプトを配置し、ファイル数が60を超える場合は、フォルダから最も古いファイルを削除したいと思います。後入選出法。頑張りましたが、

#!/bin/ksh  
for dir in /home/DABA_BACKUP  
do  
    cd $dir  
    count_files=`ls -lrt | wc -l`   
    if [ $count_files -gt 60 ];  
    then  
        todelete=$(($count_files-60))  
        for part in `ls -1rt`  
        do  
            if [ $todelete -gt 0 ]  
            then  
                rm -rf $part  
                todelete=$(($todelete-1))  
            fi  
        done  
    fi
done   

毎日保存され、名前が付けられているバックアップファイルbackup_$date。これは大丈夫ですか?

答え1

いいえ、まず改行を含むファイル名が破損します。また、必要以上に複雑で、次のようなすべてのリスクを抱えています。lsを解析する

より良いバージョンは次のとおりです(GNUツールを使用)。

#!/bin/ksh  
for dir in /home/DABA_BACKUP/*
do
    ## Get the file names and sort them by their
    ## modification time
    files=( "$dir"/* );
    ## Are there more than 60?
    extras=$(( ${#files[@]} - 60 ))
    if [ "$extras" -gt 0 ]
    then
    ## If there are more than 60, remove the first
    ## files until only 60 are left. We use ls to sort
    ## by modification date and get the inodes only and
    ## pass the inodes to GNU find which deletes them
    find dir1/ -maxdepth 1 \( -inum 0 $(\ls -1iqtr dir1/ | grep -o '^ *[0-9]*' | 
        head -n "$extras" | sed 's/^/-o -inum /;' ) \) -delete
    fi
done

これは、すべてのファイルが同じファイルシステムにあると仮定します。そうしないと、予期しない結果(誤ったファイルの削除など)が発生する可能性があります。同じ inode を指す複数のハードリンクがある場合でも、正常に動作しません。

答え2

#! /bin/zsh -
for dir (/home/DABA_BACKUP/*) rm -f $dir/*(Nom[61,-1])

~のためzsh - 無知;-):

  • for var (list) cmd:ループの短いバージョンですfor var in list; do cmd; done(構文を思い出させますperl)。
  • $dirzsh他のシェルのように変数をzsh引用する必要はありません。明らかに split演算子なので、glob暗黙的に実行しないでください。分割+グローバルパラメータが拡張された場合。
  • *(...):そしてグローバル予選:
  • N::nullglob不一致がある場合、エラーを発生させるのではなく、glob は null に拡張されます。
  • m:ああ生成されたファイルを次の場所に配置します。修正時間(最も小さいものから)。
  • [61,-1]:ソートされたリストの下部から61番目の項目を選択します。

したがって、デフォルトでは、60の最も若いファイルを除くすべてのファイルが削除されます。

答え3

削除する最も古いアイテムのリストを取得するには(最新のアイテムを60個保持):

ls -t | tail -n +61

アプローチの主な問題はまだここで解決する必要があります。場合に備えてファイルを処理する方法(やや複雑なプログラムを置き換える):

cd /home/DABA_BACKUP || exit 1
ls -t | tail -n +61 | xargs rm -rf


注:あなたが持っているように見えるので毎日のバックアップfindたとえば、ファイル日付の合計に基づいた方法を使用することもできます。

find /home/DABA_BACKUP -mtime +60 -exec ls {} +

lsこのコマンドは正しい動作を再確認した後、適切なコマンドに置き換えられますrm。)

答え4

ファイル名がすべてbackup_ *であることがわかっている場合は、そのファイルのみを処理し、誤ってディレクトリに入ったファイルを処理しないように、そのファイルをlsコマンドに含める必要があります。その後、パイプラインでlsを使用して1行に1つのファイルのみをリストし、数だけカウントするため、ソートは不要です。

count_files=$(ls -U backup_* | wc -l)

そして

for part in $(ls -rt backup_*);do
    rm -rf "$part"
    todelete=$(($todelete-1))
    if [[ $todelete -eq 0 ]]; then
        break
    fi
done

関連情報