スクリプトを作成して5分ごとにcrontabで実行しようとしているので、フォルダー内のファイルの数は常に50000のままです。それ以上ある場合は、スクリプトで古いファイルを削除します。
#!/bin/bash
LIMIT=500000
NO=0
#Get the number of files, that has `*.pcap` in its name, with last modified time 5 days ago
NUMBER=$(find /mnt/md0/capture/DCN/ -maxdepth 1 -name "*.pcap" |wc -l)
if [[ $NUMBER -gt $LIMIT ]] #if number greater than limit
then
del=$(($NUMBER-$LIMIT))
if [ "$del" -lt "$NO" ]
then
del=$(($del*-1))
fi
echo $del
FILES=$(
find /mnt/md0/capture/DCN/ -maxdepth 1 -type f -name "*.pcap" -print0 |
xargs -0 ls -lt |
tail -$del |
awk '{print $8}'
)
rm -f ${FILES[@]}
#delete the originals
fi
ファイルの数が多すぎるため、実際には機能しません。実行されません。これを行う他の方法はありますか?
コマンドを実行しました:
find /mnt/md0/capture/DCN/ -maxdepth 1 -type f -name "*.pcap" -print0 |
xargs -0 ls -lt | tail -n "$del" | awk '{print $8}'
私が観察した問題は、awk '{print $8}'
がファイル名ではなく、時刻を出力することでした。 awk '{print $9}'
はそれを解決します。
もう1つの問題は、xargs
がls -lt
を数回実行する可能性があることです。これにより、並べ替えられたファイルのリストが次々に表示されますが、リスト全体が並べ替えられません。
しかし、他にも単純化できるようです。次の方法で最も古いファイルを取得できます。
ls -dt /mnt/md0/capture/DCN/*.pcap | tail -n "$del"
これは、あなたの投稿がそうであるように、ファイル名にスペース、タブ、または改行文字が含まれていないことを前提としています。
したがって、最も古い$del
ファイルを削除するための完全なコマンドは次のようになります。
ls -dt /mnt/md0/capture/DCN/*.pcap | tail -n "$del" | xargs rm
MORE:ファイル名にスペース、タブ、バックスラッシュ、または引用符が含まれている可能性がある場合(ただし、not改行)、 (GNU ls
4.0(1998)以降を想定):
ls -dt --quoting-style=Shell-always /mnt/md0/capture/DCN/*.pcap |
tail -n "$del" | xargs rm
ファイルの名前を推測したくない人のために:
zsh
の場合:
#! /bin/zsh -
keep=5000
rm -f /mnt/md0/capture/DCN/*.pcap(D.om[$((keep+1)),-1])
zsh
グロブ修飾子を使用しています。
D
:隠しファイルを含む(Dotファイル)。.
:通常のファイルのみ(find
の-type f
など)om
:リバース o年齢に基づいて(に基づいて m改造時間)[$((keep+1)),-1]
:5001のみを含めるst 最後まで。(削除するファイルのリストが非常に大きい場合は失敗する可能性があります。その場合は、zargs
を使用して分割するか、zsh
の組み込みrm
をzmodload zsh/files
で有効にすることができます。 )。
GNUツールの比較的最近のバージョンでは:
cd /mnt/md0/capture/DCN/ &&
find . -maxdepth 1 -name '*.pcap' -type f -printf '%T@@%p\0' |
sort -zrn | sed -z "s/[^@]*@//;1,$keep d" | xargs -r0 rm -f
(-z
の場合はGNU sed 4.2.2以上(2012)、-z
の場合はGNU sort
1.14以上(1996))と仮定)
find
は、Unixタイムスタンプが先頭に付いた(1390682991.0859627500@./file
などの)ファイル名のNUL区切りリストを作成し、sort
でソートします。 sed
はタイムスタンプを削除し、5001からのみ出力しますst 記録。これは、xargs -r0
を使用して引数としてrm
に渡されます。
または(任意のバージョンのGNUツール):
cd /mnt/md0/capture/DCN/ &&
find . -maxdepth 1 -name '*.pcap' -type f -printf '%T@@%p\0' |
tr '\0\n' '\n\0' | sort -rn | tail -n "+$(($keep+1))" |
cut -d @ -f2- | tr '\0\n' '\n\0' | xargs -r0 rm -f
タイムスタンプを削除するためにcut
を使用し、5001から始まる行を選択するためにtail
を使用していることを除いて、同じです。GNU cut
tail
は、NULで区切られたレコードを処理するための-z
をサポートしていません。データをフィードする前後に、tr
を使用して改行文字とNUL文字を交換します。
GNU ls
(4.0(1998)以降)、およびbash
の場合:
shopt -s dotglob
cd /mnt/md0/capture/DCN/ &&
eval "files=($(ls -dt --quoting-style=Shell-always -- *.pcap))" &&
rm -f -- "${files[@]:$keep}"
(ファイルのリストが大きい場合にも失敗する可能性があります。また、非正規のpcapファイル(-type f
なし)が含まれる場合があることに注意してください)。
標準的に/ POSIXly /ポータブルに、それは非常にトリッキーです:
cd /mnt/md0/capture/DCN/ &&
ls -dt ./.pcap ./.*.pcap ./*.pcap | awk -v keep="$keep" '
function process() {
if (++n > keep) {
gsub(/[ \t\n"\\'\'']/,"\\\\&", file)
print file
file = ""
}
}
/\// {
if (NR > 1) process()
file=$0
next
}
{file = file "\n" $0}
END {if (NR > 0) process()}' | xargs rm -f
(ここでも、引数の数の制限に達する可能性があり、通常のファイルをチェックしません)。
トリッキーな点は、ファイル名を改行文字で処理することです。上記では、./*
をls
に渡します。これは、/
がファイル名ごとに1回含まれることを意味し、awk
でそれを使用して、各ファイル名がどの行から始まるかを識別します。 (xargs
に特別な他のすべての文字に加えて)xargs
のためにエスケープするnewline文字。
どのファイル名にもスペース、タブ、改行、一重引用符、二重引用符、または円記号が含まれていないと仮定すると、これにより、制限を超える最も古いファイルが削除されます。
mkdir t && cd t
# 50500 files, 500 to delete
touch {000001..050500}
limit=50000
ls -t|tail -n "+$(($limit + 1))"|xargs rm
ls|wc -l
50000
tail -n +50001
は制限を超えるファイルを表示します。
降順の並べ替えでls
を使用するだけです-t
:
limit=5000
Cnt=0
for line in `ls -t`
do
if [[ $Cnt -gt $limit ]]
then
rm $line
fi
Cnt=`expr $Cnt + 1`
done