使用shell巧妙高效的批量刪除歷史文件或目錄

背景:有實時產生的數據按小時分文件保存,如「/data/2013/09/18/14.txt」。現須要保留30天的最新數據,而刪除全部其它的歷史數據。注意「保留30天的最新數據」,可能不是連續的30天,中間若某一天數據缺失,也必須把最新的30天的數據保留下來。php

 

思路:獲取全部數據路徑列表,去除最新30天的數據路徑,而後遍歷刪除。如果使用腳本語言來開發(如php,python),循環獲取路徑列表的代碼就已經比較臃腫了,效率也不高,特別是文件目錄特多的時候。使用shell應該更方便和高效python

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]}}'`shell

詞命令還存在一個隱患,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,效率仍是有些不滿意,使勁的尋找更高效獲取路徑列表的方式。哈哈,黃天不負苦心人啊,終於找到一個.net

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倍blog

 

但鬱悶的是,我不知道「echo /data/*/*/*/「究竟是怎麼個原理,有什麼限制等等,網上也尚未搜索到相關資料,有知道的朋友請告知一下啊開發

 


2013-10-17 編輯補充:for循環

原命令還能夠修改精簡一下,經過指定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 $files; #輸出日誌
echo -e $files | xargs -I{} -d " " rm -rf {}

說明:
ls :  -1參數表示一個文件或目錄單獨佔一行顯示, -r 表示按路徑降序排列(默認是升序排列)

xargs: -d 參數設置分隔符

相關文章
相關標籤/搜索