不知道大家那有沒有要清理的這個事情。需要清理目錄曆史檔案。可能後續也會有很多其他地方需要清理曆史檔案,可能會用到。
我這兩天空閑寫了個指令碼,清理比較方便,有要進行清理的大量曆史檔案的話可以用。
指令碼用到的命令只有linux才有,像solaris等就不支援,所以只能在linux上運行。如果是nas儲存的話,可以掛載到一個linux主機上跑指令碼清理。
另外,指令碼尋找檔案用的是ls,但是ls也有最大檔案的限度(大概10w以內),如果每天檔案很多,每天都是10w+的,運行可能提示檔案數過多無法ls。
還有,指令碼內有個預設的限制,就是清理的檔案的建立日期是跟檔案名稱上的時間是相同的,如果是不同的話,是不會清理的,這是為了避免清理錯了。
我寫了兩個版本的清理指令碼,一個是直接清理檔案的clearfile.sh,一個是把檔案按天/月進行歸檔(歸檔成檔案夾或壓縮包形式)clearfile_ar.sh:
(一)單純清理檔案使用clearfile.sh
檔案名稱是帶有時間戳記的檔案,類似如下(或其他時間格式,後面描述)
按天/月清理:修改指令碼內的CLEAR_TYPE參數,D是天,M是月
如果是按月的話,指令碼按你輸入的月份進行整月清理,不會看你輸入的天的時間
清理指定期間內所有檔案:
./clearfile.sh/wls/investop/tmp/ 20170515 20170516
清理指定期間內固定大小檔案(ls -l顯示的大小):
./clearfile.sh /wls/investop/tmp/ 20170515 20170516 40
其他檔案日期格式清理:
指令碼預設(TRUNC_DATE_FLAG參數為N)是清理上面截圖這類格式的,沒有任何間隔符的檔案名稱。
如果檔案名稱是有其他間隔符的,如*2017_05_16*這種的。
首先需要調整下指令碼裡的trunc()方法,把標黃的年月日之間的分隔字元改成需要的分隔字元(按天和按月兩種哦)
然後再設定TRUNC_DATE_FLAG參數為Y,來讓指令碼使用你指定的日期格式清理
(二)歸檔方式清理曆史檔案,使用clearfile_ar.sh
使用方式與clearfile.sh相同,唯一不同的是要設定指令碼裡的DEL_FLAG參數。
按天/月清理同clearfile.sh
清理指定期間內所有檔案同clearfile.sh
清理指定期間內固定大小檔案 同clearfile.sh
其他檔案日期格式清理 同clearfile.sh
模式1:DEL_FLAG=N 指令碼只會把檔案按天 / 按月歸檔到以時間命名的檔案夾內,如
模式2:DEL_FLAG=Y 把檔案歸檔成壓縮檔 *tar.gz ,並刪除歸檔的檔案夾
PS,對於大量需要清理的目錄,可以寫一個非常簡單的指令碼來批量執行,類似
但是要去掉指令碼裡的是否確認執行這個反饋,否則指令碼執行還是要你輸入Y。
~~~~~~~~~~~~~~~~~~指令碼如下~~~~~~~~~~~~~~~~~~
clearfile.sh
#!/bin/bash##################################參數設定################################TODAY=`date +%Y%m%d`DATE_BEGIN=`date +%Y%m%d`DATE_END=`date +%Y%m%d`DATE_FORMATION="%Y%m%d"FILESIZE=""COUNTING=0#需要手工設定,按月清理不會根據輸入日期的天清理,只能清理整個月。CLEAR_TYPE=M#需要手工設定,是否需要轉換日期格式,需要的話,要根據格式設定trunc()方法TRUNC_DATE_FLAG=Nif [ -f count.tmp ] thenecho "" > count.tmpfi##################################日期格式轉換,eg:trunc 20170512################################trunc(){if [ "D" = "$CLEAR_TYPE" ]thenOPR_DATE=`echo $1 | sed -r 's/^(.{4})(.{2})(.{2})$/\1_\2_\3/g'`elseOPR_DATE=`echo $1 | sed -r 's/^(.{4})(.{2})$/\1_\2/g'`fi}##################################按日清理遞迴################################dayclear(){ echo "================================" echo "day clear working on $DATE_END" doclear $DATE_END priday $DATE_END if [ $DATE_END -lt $DATE_BEGIN ] then echo "================================" echo "Total cleard : $COUNTING " echo "dayclear end" return fi dayclear }##################################按月清理遞迴################################monthclear(){ echo "================================" echo "clearfun working on $DATE_END" doclear $DATE_END primonth $DATE_END if [ $DATE_END -lt $DATE_BEGIN ] then echo "================================" echo "Total cleard : $COUNTING " echo "monthclear end" return fi monthclear }##################################前一日日期,eg:priday 20170421################################priday(){ SEC=`date -d $1 +%s` PRI_SEC=$[${SEC}-86400] PRI_DAY=`date -d @${PRI_SEC} +%Y%m%d` DATE_END=$PRI_DAY}##################################前一月日期,eg:primonth 201704################################primonth(){ #TMP_D=`echo $1 | cut -c 1-6` #TMP_D=${TMP_D}"01" TMP_D=`echo $1`"01" SEC=`date -d $TMP_D +%s` PRI_SEC=$[${SEC}-86400] PRI_MON=`date -d @${PRI_SEC} +%Y%m` DATE_END=$PRI_MON}##################################清理檔案################################doclear(){ #預設的日期格式,如20170512,201705 THE_DATE=$1 OPR_DATE=$1 #轉換OPR_DATE的日期格式,如2017-05-12,2017-05 if [ "Y" = ${TRUNC_DATE_FLAG} ] ; then trunc $1 fi echo "clearing" if [ "" == "${FILESIZE}" ] then #ROW=`ls -l *${OPR_DATE}* | awk '{ print $9;output="ls -l "$9;system(output);}' | wc -l` ls -ld --time-style +${DATE_FORMATION} *${OPR_DATE}* | grep -v archive | awk -v date_str=${THE_DATE} 'BEGIN{count=0}{if (date_str==$6) {count+=1;output="rm "$7;system(output);}}END{oo="echo "count" > count.tmp";system(oo);}' ROW=`cat count.tmp` COUNTING=$[ $COUNTING + $ROW ] else #ROW=`ls -l *${OPR_DATE}* | awk -v the_size=${FILESIZE} '{if ($5==the_size) {output="ls -l "$9;system(output)}}' | wc -l` ls -ld --time-style +${DATE_FORMATION} *${OPR_DATE}* | awk -v the_size=${FILESIZE} -v date_str=${THE_DATE} 'BEGIN{count=0}{if (the_size==$5 && date_str==$6) {count+=1;output="rm "$7;system(output);}}END{oo="echo "count" > count.tmp";system(oo);}' ROW=`cat count.tmp` COUNTING=$[ $COUNTING + $ROW ] fi echo "clear $THE_DATE finished, clear file $ROW "}######################################### main function## 判斷參數是否正確,可以輸入如下:## 清理所有檔案:clear 20150601 20161231 ## 清理固定大小位元組檔案:clear 20150601 20161231 40## 清理固定大小位元組檔案:clear 20150601 20161231 40########################################清理所有檔案,if [ $# -ne 3 ] && [ $# -ne 4 ]thenecho "請輸入正確的參數"echo "如清理/nfsc/hipo/bak目錄下,從2015年4月1號到2016年12月31號的所有檔案(預設按日清理):clearfile /nfsc/hipo/bak 20150401 20161231"echo "或清理清理/nfsc/hipo/bak目錄下,從2015年4月1號到2016年12月31號的大小為40位元組的檔案(預設按日清理):clearfile /nfsc/hipo/bak 20150401 20161231 40"exit 1elseDATE_BEGIN=$2DATE_END=$3FILESIZE=$4date -d $2 2>&-ERR1=$?date -d $3 2>&-ERR2=$?if [ $ERR1 -eq 1 ] || [ $ERR2 -eq 1 ]; then echo "date formation error, input the correct date string like 20170131." exit 1elif [ $DATE_BEGIN -gt $DATE_END ]; then echo "BEGIN DATE is later than END DATE, please correct." exit 1elif [ $TODAY -lt $DATE_END ]; then echo "END DATE is later than NOW DATE, please correct"elif [ ! -d $1 ]; then echo "DIR $1 does not exist." exit 0fifi cd $1 THEDIR=`pwd` echo ">>>>clear the DIR $THEDIR " echo ">>>>clear file between $DATE_BEGIN and $DATE_END." if [ "" == "${FILESIZE}" ]; then echo ">>>>every size of the files will be clear" else echo ">>>>clear filesize only is ${FILESIZE}" fi if [ "D" == "${CLEAR_TYPE}" ]; then echo ">>>>clear set by DAY" else echo ">>>>clear by MONTH" fi read -p "please confirm the information above,enter Y to continue, other to exit : " ANWSER #確認繼續 if [ ! -n "$ANWSER" ] || [ $ANWSER != Y ] then echo "exit" exit 0 fiecho "[`date +%Y%m%d-%H%M%S`]==START=="if [ "D" = "$CLEAR_TYPE" ]then echo "DAY clear begin " DATE_FORMATION="%Y%m%d" dayclearelse echo "MONTH clear begin " DATE_BEGIN=`echo $2 | cut -c 1-6` DATE_END=`echo $3 | cut -c 1-6` DATE_FORMATION="%Y%m" monthclearfiecho "[`date +%Y%m%d-%H%M%S`]==END=="
clearfile_ar.sh
#!/bin/bash##################################參數設定################################TODAY=`date +%Y%m%d`DATE_BEGIN=`date +%Y%m%d`DATE_END=`date +%Y%m%d`DATE_FORMATION="%Y%m%d"FILESIZE=""COUNTING=0#需要手工設定,按月清理不會根據輸入日期的天清理,只能清理整個月。CLEAR_TYPE=M#需要手工設定,是否刪除歸檔的檔案,只保留壓縮檔DEL_FLAG=N#需要手工設定,是否需要轉換日期格式,需要的話,要根據格式設定trunc()方法TRUNC_DATE_FLAG=Nif [ -f count.tmp ] thenecho "" > count.tmpfi##################################日期格式轉換,eg:trunc 20170512################################trunc(){if [ "D" = "$CLEAR_TYPE" ]thenOPR_DATE=`echo $1 | sed -r 's/^(.{4})(.{2})(.{2})$/\1_\2_\3/g'`elseOPR_DATE=`echo $1 | sed -r 's/^(.{4})(.{2})$/\1_\2/g'`fi}##################################按日清理遞迴################################dayclear(){ echo "================================" echo "day clear working on $DATE_END" doclear $DATE_END priday $DATE_END if [ $DATE_END -lt $DATE_BEGIN ] then echo "================================" echo "Total cleard : $COUNTING " echo "dayclear end" return fi dayclear }##################################按月清理遞迴################################monthclear(){ echo "================================" echo "clearfun working on $DATE_END" doclear $DATE_END primonth $DATE_END if [ $DATE_END -lt $DATE_BEGIN ] then echo "================================" echo "Total cleard : $COUNTING " echo "monthclear end" return fi monthclear }##################################前一日日期,eg:priday 20170421################################priday(){ SEC=`date -d $1 +%s` PRI_SEC=$[${SEC}-86400] PRI_DAY=`date -d @${PRI_SEC} +%Y%m%d` DATE_END=$PRI_DAY}##################################前一月日期,eg:primonth 201704################################primonth(){ #TMP_D=`echo $1 | cut -c 1-6` #TMP_D=${TMP_D}"01" TMP_D=`echo $1`"01" SEC=`date -d $TMP_D +%s` PRI_SEC=$[${SEC}-86400] PRI_MON=`date -d @${PRI_SEC} +%Y%m` DATE_END=$PRI_MON}##################################清理檔案################################doclear(){ #預設的日期格式,如20170512,201705 THE_DATE=$1 OPR_DATE=$1 #轉換OPR_DATE的日期格式,如2017-05-12,2017-05 if [ "Y" = ${TRUNC_DATE_FLAG} ] ; then trunc $1 fi #建立歸檔檔案夾 echo "clearing" if [ ! -d ${THE_DATE}"archive" ] ;then mkdir "${THE_DATE}"archive ERR=$? if [ 0 != ${ERR} ]; then echo "failed to create archive dir under "`pwd` exit 0 fi echo "created the archive directory ${THE_DATE}archive" chmod 777 ${THE_DATE}"archive" else echo "the archive directory already exist ${THE_DATE}archive" fi #如果要刪除曆史的歸檔檔案,判斷是否已經存在過曆史檔案的壓縮包 if [ -f "${THE_DATE}archive.tar.gz" ] && [ "Y" = "${DEL_FLAG}" ] ;then echo "file ${THE_DATE}archive.tar.gz already exits, and again you choose to archive the file which had been archived ,this will cause the old tar.gz file tobe overwirted." echo "you should confirm the date parameter you input, or you can mv the exits *.tar.gz file to other directory." exit 0 fi if [ "" == "${FILESIZE}" ] then ls -ld --time-style +${DATE_FORMATION} *${OPR_DATE}* | grep -v archive | awk -v date_str=${THE_DATE} 'BEGIN{count=0;}{if (date_str==$6) {count+=1;output="mv "$7" "date_str"archive/";system(output);}}END{oo="echo "count" > count.tmp";system(oo);}' if [ "Y" = "${DEL_FLAG}" ] ; then tar -cf - ${THE_DATE}"archive/" | gzip > ${THE_DATE}"archive.tar.gz" rm -rf ${THE_DATE}"archive/" fi ROW=`cat count.tmp` COUNTING=$[ $COUNTING + $ROW ] else ls -ld --time-style +${DATE_FORMATION} *${OPR_DATE}* | grep -v archive | awk -v the_size=${FILESIZE} -v date_str=${THE_DATE} 'BEGIN{count=0;}{if (the_size==$5 && date_str==$6) {count+=1;output="mv "$7" "date_str"archive/";system(output);}}END{oo="echo "count" > count.tmp";system(oo);}' if [ "Y" = "${DEL_FLAG}" ] ; then tar -cf - ${THE_DATE}"archive/" | gzip > ${THE_DATE}"archive.tar.gz" rm -rf ${THE_DATE}"archive/" fi ROW=`cat count.tmp` COUNTING=$[ $COUNTING + $ROW ] fi echo "clear $THE_DATE finished, clear file $ROW "}######################################### main function## 判斷參數是否正確,可以輸入如下:## 清理所有檔案:clear 20150601 20161231 ## 清理固定大小位元組檔案:clear 20150601 20161231 40## 清理固定大小位元組檔案:clear 20150601 20161231 40########################################清理所有檔案,if [ $# -ne 3 ] && [ $# -ne 4 ]thenecho "請輸入正確的參數"echo "如清理/nfsc/hipo/bak目錄下,從2015年4月1號到2016年12月31號的所有檔案(預設按日清理):clearfile /nfsc/hipo/bak 20150401 20161231"echo "或清理清理/nfsc/hipo/bak目錄下,從2015年4月1號到2016年12月31號的大小為40位元組的檔案(預設按日清理):clearfile /nfsc/hipo/bak 20150401 20161231 40"exit 1elseDATE_BEGIN=$2DATE_END=$3FILESIZE=$4date -d $2 2>&-ERR1=$?date -d $3 2>&-ERR2=$?if [ $ERR1 -eq 1 ] || [ $ERR2 -eq 1 ]; then echo "date formation error, input the correct date string like 20170131." exit 1elif [ $DATE_BEGIN -gt $DATE_END ]; then echo "BEGIN DATE is later than END DATE, please correct." exit 1elif [ $TODAY -lt $DATE_END ]; then echo "END DATE is later than NOW DATE, please correct"elif [ ! -d $1 ]; then echo "DIR $1 does not exist." exit 0fifi cd $1 THEDIR=`pwd` echo ">>>>clear the DIR $THEDIR " echo ">>>>clear file between $DATE_BEGIN and $DATE_END." if [ "" == "${FILESIZE}" ]; then echo ">>>>every size of the files will be clear" else echo ">>>>clear filesize only is ${FILESIZE}" fi if [ "D" == "${CLEAR_TYPE}" ]; then echo ">>>>clear set by DAY" else echo ">>>>clear by MONTH" fi read -p "please confirm the information above,enter Y to continue, other to exit : " ANWSER #確認繼續 if [ ! -n "$ANWSER" ] || [ $ANWSER != Y ] then echo "exit" exit 0 fiecho "[`date +%Y%m%d-%H%M%S`]==START=="if [ "D" = "$CLEAR_TYPE" ]then echo "DAY clear begin " DATE_FORMATION="%Y%m%d" dayclearelse echo "MONTH clear begin " DATE_BEGIN=`echo $2 | cut -c 1-6` DATE_END=`echo $3 | cut -c 1-6` DATE_FORMATION="%Y%m" monthclearfiecho "[`date +%Y%m%d-%H%M%S`]==END=="
歡迎各位博友提出更新意見。
謝謝