通過刪除舊文件來保持文件夾中的文件數量不變
我正在嘗試創建一個腳本並每 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}'
會解決的。另一個問題是它
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
**更多:**如果您的文件名可能包含空格、製表符、反斜杠或引號(但不包含換行符),請使用(假設 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
: 包括隱藏文件(D ot 文件)。.
: 僅正常文件(如find
’s-type f
)om
: 年齡倒序**(****基於**修改時間)[$((keep+1)),-1]
: 只包括到最後的第5001條。(如果要刪除的文件列表非常大,它可能會失敗,在這種情況下,您可能希望使用
zargs
它來拆分它,或者啟用zsh
’s builtinrm
withzmodload 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
(假設 GNU sed 4.2.2 或更高版本(2012)
-z
,GNUsort
1.14 或更高版本(1996)-z
)
find
建構一個 NUL 分隔的文件名列表,前面帶有 Unix 時間戳(如1390682991.0859627500@./file
),按sort
.sed
刪除時間戳並僅從第 5001條記錄中列印。這作為參數傳遞給rm
usingxargs -r0
。或(使用任何版本的 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
用於刪除時間戳並tail
選擇從 5001 開始的行。由於 GNUcut
並且tail
不支持-z
處理 NUL 分隔的記錄,我們使用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
來辨識每個文件名從哪一行開始,然後我們知道哪個換行符(除了所有其他特殊的換行符)到逃跑。/``awk``xargs``xargs