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


背景:有實時產生的數據按小時分文件保存,如“/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 $files; #輸出日志
echo -e $files | xargs -I{} -d " " rm -rf {}

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

xargs: -d 參數設置分隔符


---------------------
作者:five-zh
來源:CSDN
原文:https://blog.csdn.net/tsxw24/article/details/12013753
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM