Bash スクリプトを使用して、ディレクトリ全体のすべてのファイル (最新の 4 つを除く) を削除します。

Bash スクリプトを使用して、ディレクトリ全体のすべてのファイル (最新の 4 つを除く) を削除します。

ディレクトリのリストにアクセスし、最近作成された 4 つのファイル以外のすべてのファイルを削除する Bash スクリプトを探しています。

これどうやってするの?

答え1

ls -t | sed '1,4d' | xargs echo rm

echo希望する結果が得られたら、それを削除します。

ファイル名にスペースが含まれている場合は、さらに作業が必要になります。

答え2

各ディレクトリ内の最新の 4 つのファイルを保持しますか、それとも任意のディレクトリ内の最新の 4 つのファイルを保持しますか?

最初の問題を解決するには、find を使用して各ディレクトリを一覧表示し、各ディレクトリで最新の 4 つのファイル以外のすべてのファイルを削除します。これはそれほど難しくありません。

2 番目の問題を解決するには、もう少し考える必要がありますが、実際には書く方が簡単です。

基本的に、すべてのファイルを再帰的に検索します。ファイルの変更時刻と名前を返す「stat」コマンドを呼び出します。これを数値の降順で並べ替え、最新の最初の 4 つのファイルをスキップします。

次に、先頭のタイムスタンプを削除し、結果として得られるファイル名のリストを削除します。

次のようなもの(未テスト):

#!/bin/bash

find "$@" -type f -print0 \
| xargs -0 stat -c$'%Y\t%n' \
| sort -rn \
| awk -F$'\t' 'NR > 4 {print $2}' \
| while read f; do
    echo rm -v "${f}"
  done

これは動作するはずですが、有効にするには while ループ内の「echo」を削除する必要があります。まずは慎重にテストしてください。

答え3

これはまさにあなたが尋ねていることではないことは承知していますが、この種のバックアップでは、新しいログ ファイルを作成する前にログ ファイルをローテーションすることを好みます。次のようにすると、もう少し明確で、コードがはるかに簡単になります。

#!/bin/bash

#Archive old backups
move () {
  if [ -e $1 ]
  then
    echo "Archiving old backups: $1 to $2"
    mv -f $1 $2 || echo "FAILED"
  fi
}

#Bump each backup +1
rm -rf backup.4
move backup.3.tgz backup.4.tgz
move backup.2.tgz backup.3.tgz
move backup.1.tgz backup.2.tgz
move backup.tgz backup.1.tgz

#Now create today's backup
...

答え4

最も簡単な方法:

for d in dir1 dir2 dir3; do
  rm -vf `ls -1t $d | head -n-4` 
done

関連情報