背景:有實時産生的資料按小時分檔案儲存,如“/data/2013/09/18/14.txt”。現需要保留30天的最新資料,而删除所有其它的曆史資料。注意“保留30天的最新資料”,可能不是連續的30天,中間若某一天資料缺失,也必須把最新的30天的資料保留下來。
思路:擷取所有資料路徑清單,去除最新30天的資料路徑,然後周遊删除。若是使用腳本語言來開發(如php,python),循環擷取路徑清單的代碼就已經比較臃腫了,效率也不高,特别是檔案目錄特多的時候。使用shell應該更友善和高效
rm -rf `find /data/*/*/*/ -type d|awk '{a[NR]=$0}END{n=asort(a,sa)-30;for(i=1;i<=n;i++){print sa[i]}}'`
詞指令還存在一個隐患,rm的參數字元長度可能超過1024的限制,修改如下
find /data/*/*/*/ -type d|awk '{a[NR]=$0}END{n=asort(a,sa)-30;for(i=1;i<=n;i++){print sa[i]}}'|xargs -I{} rm -rf {}
這個指令裡使用了find,效率還是有些不滿意,使勁的尋找更高效擷取路徑清單的方式。哈哈,黃天不負苦心人啊,終于找到一個
echo /data/*/*/*/|awk '{for(i=1;i<=NF;i++){a[i ]=$i}}END{n=asort(a,sa)-30;for(i=1;i<=n;i++){print sa[i ]}}'|xargs -I{} rm -rf {}
使用time指令測試運作速度,第二條指令和第三條指令其運作時間分别是0.007s和0.002s,後者快了3倍
但郁悶的是,我不知道“echo /data/*/*/*/“到底是怎麼個原理,有什麼限制等等,網上也還沒有搜尋到相關資料,有知道的朋友請告知一下啊
2013-10-17 編輯補充:
原指令還可以修改精簡一下,通過指定awk使用的換行符來避免for循環
echo /data/*/*/*/|awk 'BEGIN{ORS=RS=" "}{a[NR]=$0}END{n=asort(a,sa)-30;for(i=1;i<=n;i++){print sa[i ]}}'|xargs -I{} rm -rf {}
還有一個問題就是,你可能想在日志中記錄下删除了那些檔案。可以先把檔案清單指派給一個變量,記錄日志後再删除
files=`echo /data/*/*/*/|awk 'BEGIN{ORS=RS=" "}{a[NR]=$0}END{n=asort(a,sa)-30;for(i=1;i<=n;i++){print sa[i ]}}'`
echo $files; #輸出日志
echo -e ${files//\ /"\n"}|xargs -I{} rm -rf {}
關鍵是最後一行, echo 的-e參數是為了可以輸出\n換行,如無此參數則不會識别。
${files//\ /"\n"} 是把變量files裡的所有空格都替換成\n換行符,這樣xargs才能正确切分參數。不知道為什麼會這樣
2015-4-16 繼續優化指令
files=`ls -1 -r /data/*/*/*/ | awk 'NR>=30{print $0}'`
echo -e $files | xargs -I{} -d " " rm -rf {}
說明:
ls : -1參數表示一個檔案或目錄單獨占一行顯示, -r 表示按路徑降序排列(預設是升序排列)
xargs: -d 參數設定分隔符
---------------------
作者:five-zh
版權聲明:本文為部落客原創文章,轉載請附上博文連結!